3.7 KiB
C# Language Design Notes for Oct 17, 2018
Agenda
- Open issues with default interface methods
- Target typed new with default constructors on structs
Discussion
Issues in default interface methods
Link: https://github.com/dotnet/csharplang/issues/406
Diamond inheritance
We've come down to two options: pick an implementation somewhat arbitrarily, or produce a runtime exception. The positive about picking one is that we more strongly provide the guarantee that adding a default method implementation will not "break" the application. The minus is that there's no guarantee that the method we actually picked is the correct one.
It's also noted that adding a virtual method to a base class can implement an interface in the derived class, but you can get the same result just through current language behavior:
interface IFoo { void M() { impl; } }
class Derived : Base, IFoo {}
class Base : Base0
{
public virtual void M() {} // added later
}
class Base0 : IFoo
{
void IFoo.M() { }
}
Conclusion
We're going to throw a runtime exception (we want a new exception type) when there is a runtime diamond and there is no unique most derived implementation. We've decided that the exception will be thrown at method resolution time, so the exception would be thrown when taking a delegate to the target method, rather than when the delegate is invoked. We should note in documentation when this kind of change could be a source or binary breaking change.
We'd like to have some method to provide static verification, as long as we can provide a tool that has access to the runtime environment (like the IL linker).
Permit partial in interface?
Partial methods, in addition to the partial type?
Conclusion
Yes, with the same restrictions as in classes.
Main
in an interface?
No reason why not.
Confirm that we support public non-virtual methods
Yes, we'll support it.
Does an override
in an interface introduce a new member?
No override keyword in interfaces. This should resolve all listed questions.
Properties with a private accessor
We say that private members are not virtual, and the combination of virtual and private is disallowed. But what about a property with a private accessor?
interface IA
{
public virtual int P
{
get => 3;
private set => { }
}
}
Is this allowed? Is the set
accessor here virtual
or not? Can it be overridden where it is accessible? Does the following implicitly implement only the get
accessor?
class C : IA
{
public int P
{
get => 4;
set { }
}
}
Is the following presumably an error because IA.P.set isn't virtual and also because it isn't accessible?
class C : IA
{
int IA.P
{
get => 4;
set { }
}
}
The first example looks valid, while the last does not. This is resolved analogously to how it already works in C#.
Warning for struct not implementing default method?
This seems like something more suited for an analyzer. It also seems like this warning could be noisy, since it would fire even if the default interface method is never called and no boxing will ever occur.
When are interface static constructors run?
On the desktop CLR, static methods on interfaces currently run the static constructor on entry if it has not already been run. It's proposed that we adopt the same behavior for instance methods.
Conclusion
Static constructors are also run on entry to instance methods, if the static
constructor was not beforefieldinit
, in which case static constructors are
run before access to the first static field.
Target-typed new()
Can you use new() on anything that has a valid constructor? Like int
? Or a
tuple?
Conclusion
Yes.