I've been messing around with the default interface implementations. Figured you have to de a downcast to the interface type to use a default method implementation. I also found a bunch of notes on another syntax, I can't find if this is already included or not, I did find "decisions" on how it's going to look, it doesn't work however. Am I doing it wrong or is this new syntax not included yet?
Somewhat related but doesn't answer my question: Calling C# interface default method from implementing struct without boxing
Notes on the base<>/base()
syntax: https://github.com/dotnet/csharplang/blob/master/meetings/2018/LDM-2018-11-14.md#default-interface-implementations
Microsoft's page on the proposal: https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/proposals/csharp-8.0/default-interface-methods
class D : IA, IB, IC
{
//Notice the use of base() right here.
void IA.M() { base(IB).M(); }
}
So say we need INotifyPropertyChanged on some object. We can now have a SetField implementation as default on an interface:
public interface INotify : INotifyPropertyChanged
{
void InvokePropertyChanged(string propertyName);
bool SetField<T>(ref T field, T value, [CallerMemberName] string propertyName = null)
{
INotify thing = (INotify)this;
if (propertyName == null)
{
throw new ArgumentException($"{nameof(propertyName)} is null. PropertyChangedEventHandler will not be fired correctly.");
}
if (EqualityComparer<T>.Default.Equals(field, value)) return false;
field = value;
InvokePropertyChanged(propertyName);
return true;
}
}
Implementing it needs a downcast (((INotify)this).SetField
), using base(INotify)
would be preferred here.
public class Thing : INotify
{
public string A
{
get => _a;
//Need an explicit cast here. Can't figure out how to use base syntax.
set => ((INotify)this).SetField(ref _a, value);
}
private string _a;
public event PropertyChangedEventHandler PropertyChanged;
public void InvokePropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}