abstract, virtual and sealed methods in interfaces of C#-8 - c#

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?

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.

Related

Why isn't keyword override used when implementing methods from interfaces? C#

interface A1 {
void jj();
void ff() { /* */}
}
class B1 : A1 {
public void jj() { }
void ff() { /* */}
}
I am implementing two methods in the B1 class: the jj(), which does not have a default implementation in the interface A1, and the ff(), which does have a default implementation in the interface A1.
I am wondering why do not we use the override keyword when implementing a method from an interface since those methods in the interfaces are wither abstract or virtual?:
jj : abstract
ff : virtual
10 years ago, you could say that it is because the interface does not have a default implementation and that is why we do not override, we implement. BUT starting from C# 8.0 default implementations are possible and so why is that that we are not OBLIGED to use the override keyword?
As msdn docs says about Default interface members:
These preceding member declarations typically don't contain a body.
Beginning with C# 8.0, an interface member may declare a body. Member
bodies in an interface are the default implementation. Members with
bodies permit the interface to provide a "default" implementation for
classes and structs that don't provide an overriding
implementation.
and:
Beginning with C# 11, an interface may define static abstract or
static virtual members to declare that an implementing type must
provide the declared members. Typically, static virtual methods
declare that an implementation must define a set of overloaded
operators.
However, override keyword is not applied. It can be seen at this tutorial about static abstract interface methods.
why is that that we are not OBLIGED to use the override keyword
Because we are not overriding behavior, we are replacing behavior. I mean that we cannot call base keyword on concrete implementations of interfaces. It is like using new keyword instead of override
from c# 8 docs
The final override for IA.M in class C is the concrete method M declared in IA. Note that a class does not inherit members from its interfaces; that is not changed by this feature:
as the interface implementation is not inherited by its children there is no need to override it every declaration of an interface method by its child is the only implementation the child can have.

internal interface *less* accessible than an internal protected constructor?

I have an interface and an abstract base class defined in the same assembly:
IFoo.cs:
internal interface IFoo { ... }
Base.cs:
public abstract class Base
{
internal protected Base(IFoo foo) { ... }
}
This generates the following compiler error:
CS0051: Inconsistent accessibility: parameter type 'IFoo' is less
accessible than method 'Base.Base(IFoo)'
If I make the Base class constructor internal-only, the error goes away. Since the class is abstract, maybe adding protected to the accessibility doesn't accomplish anything...
Still, I don't understand the error. MSDN defines 'protected internal' as
"Access is limited to the current assembly or types derived from the
containing class"
How is the internal interface IFoo less accessible than an internal protected constructor?
This MSDN page defined 'protected internal' as (emphasis from original):
The protected internal accessibility level means protected OR
internal, not protected AND internal. In other words, a protected
internal member can be accessed from any class in the same assembly,
including derived classes. To limit accessibility to only derived
classes in the same assembly, declare the class itself internal, and
declare its members as protected.
So in other words, types from outside the current assembly that derive from Base would have access to Base(IFoo foo) but they wouldn't have access to IFoo, since it is internal. Thus the error.

Can a method be abstract but not virtual?

As I understand it, a method being marked abstract is implicitly virtual. The reason: Suppose the compile-time type of a given object is abstract. If one of the object's abstract methods is being called, the actual method to be executed is the one defined in the object's runtime type. Isn't it? If I'm right then the abstract method behaves as if it is also virtual.
In spite of that, I have successfully marked a C# method both abstract and virtual simultaneously:
public abstract virtual void crazy();
I suppose it means that an abstract method is not necessarily virtual and being abstract is actually orthogonal to being virtual.
What do I get wrong? How can an abstract method not be virtual?
You cannot mark a method as both abstract and virtual. It will result in a compiler error:
The abstract method 'Namespace.Class.Foo()' cannot be marked virtual
The rest of your question is correct: abstract methods are implicitly virtual.
From MSDN
An abstract method is implicitly a virtual method.
Abstract method declarations are only permitted in abstract classes.
Because an abstract method declaration provides no actual implementation, there is no method body; the method declaration simply ends with a semicolon and there are no braces ({ }) following the signature.
The implementation is provided by an overriding method, which is a member of a non-abstract class.
It is an error to use the static or virtual modifiers in an abstract method declaration.
"You cannot use the virtual modifier with the static, abstract, private, or override modifiers."
http://msdn.microsoft.com/en-us/library/9fkccyh4(v=vs.100).aspx

Implementing the Template Method pattern in C#

The template method pattern provides that the abstract base class has a not overridable method: this method implements the common algorithm and should not overridden in the subclasses. In Java the template method is declared final within the abstract base class, in C# the sealed keyword has a similar meaning, but a not overridden method can not be declared sealed.
public abstract class Base
{
protected abstract AlgorithmStep1();
protected abstract AlgorithmStep2();
public sealed void TemplateMethod() // sealed: compile error
{
AlgorithmStep1();
AlgorithmStep2();
}
}
How can I solve this problem?
Why can not prevent a method can be overridden by subclasses (in C#)?
The sealed modifier is only valid for function members which are overriding base class members, to stop them from being virtual for derived classes. Function members are non-virtual by default in C# (unlike Java). You still need the sealed modifier for a class though - classes aren't sealed by default.
Just remove the sealed modifier from your method and it should be fine.
See section 10.6.5 of the C# 4 spec for more details about sealed methods (sealed properties and events are in section 10.7.5 and 10.8.4 respectively).
When an instance method declaration includes a sealed modifier, that method is said to be a sealed method. If an instance method declaration includes the sealed modifier, it must also include the override modifier. Use of the sealed modifier prevents a derived class from further overriding the method.
Just remove the sealed keyword. By default, methods are not overridable; subclasses cannot override them, only hide them.
C# methods are sealed by default

c# abstract methods: internally public and virtual?

Are abstract methods internally public and virtual in c#?
All methods are, by default, private and if an abstract method is private, it will not be available to derived class, yielding the error "virtual or abstract members cannot be private"
I think you are asking a different question than most people think (in other words it seems like you understand what abstract means).
You cannot declare a private abstract method - the compiler issues an error. Both of these classes will not compile:
class Foo
{
private abstract void Bar();
}
class Baz
{
// This one is implicitly private - just like any other
// method declared without an access modifier
abstract void Bah();
}
The compiler is preventing you from declaring a useless method since a private abstract member cannot be used in a derived class and has no implementation (and therefore no use) to the declaring class.
It is important to note that the default access modifier applied to an abstract member by the compiler (if you do not specify one yourself) is still private just like it would be if the method was not abstract.
Abstract is just a way to say: "I am here, but no one has told me what I'm going to do yet." And since no one has implemented that member yet someone must do that. To do that you have to inherit that class, and override that member.
To be able to override something it has to be declared either abstract or virtual, and must at least be accessible to the inheritor, i.e. must be marked protected, internal or public.
Abstract methods cannot be private and are virtual. They must be at least protected.
By virtue of Jon Skeet's argument here (What are the Default Access Modifiers in C#?)
The default access for everything in C# is "the most restricted access you could declare for that member"
It must be "protected"
As pointed out by Pieter default is always private, so:
abstract class Foo
{
abstract void Bar();
}
Gives compiler error
virtual or abstract members cannot be private

Categories

Resources