abstract, virtual and sealed methods in interfaces of C# 8
Asked Answered
F

1

7

The following interface has no errors in a .NET Core Console application with C# 8.0

interface I
{
    public abstract void f();
    public virtual void g() => Console.WriteLine("g");
    public sealed void h() => Console.WriteLine("h");
}

abstract prevents adding a definition in interface. virtual and sealed necessitate a definition in interface. sealed prevents an implementation of h in derived classes.

Do abstract, virtual and sealed, when used in interfaces, have any other meaning or applications in current implemented version of C# 8? How and when should they be used in interfaces?

Fight answered 11/3, 2020 at 16:38 Comment(20)
C# 8 introduced default interface members, something that allows all of those things. An interface can provide an implementation for a member that's used if the implementing classes don't have their own implementation.Gascon
This is useful eg in versioning. Before DIMs, adding a new member to an interface would break all classes that implement it, until they also implemented that method. With DIMs, old classes don't have to change when a new member is added.Gascon
@PanagiotisKanavos I know that. My question is about abstract, virtual and sealed. What do they mean in interfaces?Fight
That's the answer. They are used with DIMs. Their use is described in all articles that describe DIMsGascon
They shouldn't, if you don't specifically need them. [public,] abstract, and virtual are redundant here. All interface members are virtual (abstract == pure virtual) and prior to C# 8.0, they were always abstract. The abstract/virtual distinction (in a class or, now, in an interface) is simply whether or not there's an implementation. sealed prevents the method from being explicitly implemented but not from being implicitly implemented, but that shouldn't be the interface designer's concern.Legrand
Have a look at this (infoq.com/articles/default-interface-methods-cs8). Hope it answer your doubt.Lobell
@Legrand what do you mean that "interface members are virtual"?Peacemaker
Interface members, by necessity, require vtable entries. That's the pre-8.0 view, though, I realize. Now you can have static members and such. But the public members that represent the interface are virtual. A public member that implements an interface member may not, itself, be virtual but when accessed via an interface reference, it's a virtual call.Legrand
@Legrand you said "sealed prevents the method from being explicitly implemented but not from being implicitly implemented". implicit implementation is also impossible with sealed. Trying to do an implicit implementation does not produce an error. But in fact it is not regarded an implementation by compiler. Just an independent function.Fight
@nano: You're right, my test was improperly done. In that case, sealed seems useless because you can't override your g method (in an interface that implements I) any more than you could override your sealed h method, and g isn't marked sealed.Legrand
A significant pedagogical problem here was the choice of "virtual". By "virtual" we mean that when you call a method you do not call the method directly; rather you call via some indirect mechanism such as a table lookup. But this is an implementation detail, and a poor description at that. Really what we mean by "virtual" in C# and C++ and other similar languages is late bound, single dispatch. That is, the choice of what method to call is determined at runtime -- late -- and the choice is made solely by examining the type of a single argument -- "this".Hispanic
If we then apply this to madreflection's statement, it becomes obviously true. "All interface members are late bound single dispatch". They have to be; when you invoke a method of an interface, you don't know which actual method will be invoked until runtime, and the exact method you get depends only on the runtime type of this. (Leaving aside the new feature of static interface members of course.)Hispanic
@EricLippert: Thank you for the correction/clarification.Legrand
I didn't intend to make a correction; rather, to explain why it is that this terminology is so confusing and how as language designers we could have made different choices that would have been less confusing. Your statement was correct.Hispanic
Oh. Then I thank you for confirming it.Legrand
@Legrand It seems you say these keywords are useless in interfaces. By useless do mean, that they have only the effects I mentioned in the question and no other effects or applications beyond that?Fight
@nano: That's correct; those keywords are intended to clarify the meaning. Unfortunately we again have a pedagogical problem. Language designers frequently have to decide whether to make these sorts of redundancies required, optional or illegal, and C# does all three. private is optional on a member; if it is omitted, you get it anyway. public static is required on a user defined operator; if it is omitted, you get an error. And until recently, virtual was illegal on an interface member because it was redundant.Hispanic
@nano: Well, I only said that sealed is useless, whereas the others are merely redundant. sealed does have an effect in that it prevents the implementing class from providing an implementation, as you pointed out. However, that's entirely contrary to the purpose of interfaces and, indeed, default interface member implementations (the default part, specifically). A sealed interface member implemented by the interface could be achieved by an extension method (even pre-8.0) and that would be more meaningful as to its intent. You'd expect to be able to provide an implementation.Legrand
@madreflection: I am currently reviewing the chapter in a C# programming book on these features and I share your concerns; having been absent from the design process for some time now it is not clear to me how the designers weighed the various options and came up with the compromise position they did. I need to do more research on this.Hispanic
@EricLippert: Looking forward to that blog post, too. ;)Legrand
S
2

This is from the proposal:

The syntax for an interface is relaxed to permit modifiers on its members. The following are permitted: private, protected, internal, public, virtual, abstract, sealed, static, extern, and partial.

An interface member whose declaration includes a body is a virtual member unless the sealed or private modifier is used. The virtual modifier may be used on a function member that would otherwise be implicitly virtual. Similarly, although abstract is the default on interface members without bodies, that modifier may be given explicitly. A non-virtual member may be declared using the sealed keyword.

It is an error for a private or sealed function member of an interface to have no body. A private function member may not have the modifier sealed.

Sienese answered 30/7, 2022 at 20:20 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.