Interface with a default implementation
-
I'm having trouble getting my mind around how a default method in an interface works. Picture the below interface and default method implementation:
public interface IClientForm { delegate void WindowClosedDelegate(object sender, WindowEventArgs args); event WindowClosedDelegate OnClosed; long FormId { get; set; } UIContextClass UIContext { get; set; } IClientForm ParentForm { get; set; } void Window\_Closed(object sender, WindowEventArgs args); }
// Below is the default method implementation
public static class IClientFormHelper { public static void SetUiContext(this IClientForm iClientForm, UIContextClass \_UiContext) { iClientForm.UIContext = \_UiContext; // I put a breakpoint here and it's never hit iClientForm.FormId = \_UiContext.AppContext.ClientGetUniqueFormId(); iClientForm.UIContext.AddForm(iClientForm); iClientForm.OnClosed += iClientForm.UIContext.Window\_Closed; } }
The main problem I see right now is that the default method code never runs. I assume the code is supposed to run as soon as I call the setter for
UIContext
that's declared in the main interface. Apparently, this is something I don't understand. What I want is for every IClientForm window to run the default code whenever the UIContext setter is called for that form, so that each separate window class doesn't need the same code repeated inside of it. Can someone spot what I've done wrong and point me in the right direction? I sincerely appreciate your time.The difficult we do right away... ...the impossible takes slightly longer.
-
I'm having trouble getting my mind around how a default method in an interface works. Picture the below interface and default method implementation:
public interface IClientForm { delegate void WindowClosedDelegate(object sender, WindowEventArgs args); event WindowClosedDelegate OnClosed; long FormId { get; set; } UIContextClass UIContext { get; set; } IClientForm ParentForm { get; set; } void Window\_Closed(object sender, WindowEventArgs args); }
// Below is the default method implementation
public static class IClientFormHelper { public static void SetUiContext(this IClientForm iClientForm, UIContextClass \_UiContext) { iClientForm.UIContext = \_UiContext; // I put a breakpoint here and it's never hit iClientForm.FormId = \_UiContext.AppContext.ClientGetUniqueFormId(); iClientForm.UIContext.AddForm(iClientForm); iClientForm.OnClosed += iClientForm.UIContext.Window\_Closed; } }
The main problem I see right now is that the default method code never runs. I assume the code is supposed to run as soon as I call the setter for
UIContext
that's declared in the main interface. Apparently, this is something I don't understand. What I want is for every IClientForm window to run the default code whenever the UIContext setter is called for that form, so that each separate window class doesn't need the same code repeated inside of it. Can someone spot what I've done wrong and point me in the right direction? I sincerely appreciate your time.The difficult we do right away... ...the impossible takes slightly longer.
Hi Richard, I haven't used default implementations yet, what struck me in your code is
IClientFormHelper
isn't referenced anywhere, and does not belong to the interface, as it sits outside the curly brackets ofpublic interface IClientForm
. If you want to know all about it, I guess Default interface methods - C# feature specifications | Microsoft Learn[^] is what you need. It seems to be a very complex matter. If all you want is some inspiration, I'd recommend https://stackoverflow.com/questions/53700939/default-interface-methods-and-default-values-for-auto-properties[^]. Cheers :)Luc Pattyn [My Articles] The Windows 11 taskbar is a disgrace; a third-party add-on is needed to reverse the deterioration. I decline such a downgrade.
-
Hi Richard, I haven't used default implementations yet, what struck me in your code is
IClientFormHelper
isn't referenced anywhere, and does not belong to the interface, as it sits outside the curly brackets ofpublic interface IClientForm
. If you want to know all about it, I guess Default interface methods - C# feature specifications | Microsoft Learn[^] is what you need. It seems to be a very complex matter. If all you want is some inspiration, I'd recommend https://stackoverflow.com/questions/53700939/default-interface-methods-and-default-values-for-auto-properties[^]. Cheers :)Luc Pattyn [My Articles] The Windows 11 taskbar is a disgrace; a third-party add-on is needed to reverse the deterioration. I decline such a downgrade.
Thanks Luc. If you say it's complex, then it must be too far for me to grasp. ;) I've decided to use the IClientFormHelper class as an extension method call, that I will just have to repeat in my IClientForm window classes.
The difficult we do right away... ...the impossible takes slightly longer.
-
Thanks Luc. If you say it's complex, then it must be too far for me to grasp. ;) I've decided to use the IClientFormHelper class as an extension method call, that I will just have to repeat in my IClientForm window classes.
The difficult we do right away... ...the impossible takes slightly longer.
Hm. The one link shows there are many aspects to the default implementation inside interfaces, that article is hard to read and understand in one go. The first answer in the SO link shows how a default property getter could be written; that is simple, and at first glance what you want could be implemented likewise as a default setter. :)
Luc Pattyn [My Articles] The Windows 11 taskbar is a disgrace; a third-party add-on is needed to reverse the deterioration. I decline such a downgrade.
-
Hm. The one link shows there are many aspects to the default implementation inside interfaces, that article is hard to read and understand in one go. The first answer in the SO link shows how a default property getter could be written; that is simple, and at first glance what you want could be implemented likewise as a default setter. :)
Luc Pattyn [My Articles] The Windows 11 taskbar is a disgrace; a third-party add-on is needed to reverse the deterioration. I decline such a downgrade.
That's one of the major things that stumped me. Since an interface can't contain data members, then if I try to write a default setter, I have nothing to assign it to. It was at that point that I gave up! EDIT: Maybe I should solve the problem by using the inheritance of a base class, rather than trying to stuff it into the interface. That gives me an idea...
The difficult we do right away... ...the impossible takes slightly longer.
-
That's one of the major things that stumped me. Since an interface can't contain data members, then if I try to write a default setter, I have nothing to assign it to. It was at that point that I gave up! EDIT: Maybe I should solve the problem by using the inheritance of a base class, rather than trying to stuff it into the interface. That gives me an idea...
The difficult we do right away... ...the impossible takes slightly longer.
You could use properties rather than variables, couldn't you? That is what the example does... :)
Luc Pattyn [My Articles] The Windows 11 taskbar is a disgrace; a third-party add-on is needed to reverse the deterioration. I decline such a downgrade.
-
You could use properties rather than variables, couldn't you? That is what the example does... :)
Luc Pattyn [My Articles] The Windows 11 taskbar is a disgrace; a third-party add-on is needed to reverse the deterioration. I decline such a downgrade.
Yes I could use properties, but at some point in the call stack, the value must be assigned to a data member in the window instance. So that's code that must be repeated in each class, unless I derive from a base class.
The difficult we do right away... ...the impossible takes slightly longer.
-
Yes I could use properties, but at some point in the call stack, the value must be assigned to a data member in the window instance. So that's code that must be repeated in each class, unless I derive from a base class.
The difficult we do right away... ...the impossible takes slightly longer.
Ah, sorry, I missed the sentence "You can't declare auto-implemented properties in interfaces" in Auto-Implemented Properties - C# | Microsoft Learn[^] . Makes sense. :)
Luc Pattyn [My Articles] The Windows 11 taskbar is a disgrace; a third-party add-on is needed to reverse the deterioration. I decline such a downgrade.
-
I'm having trouble getting my mind around how a default method in an interface works. Picture the below interface and default method implementation:
public interface IClientForm { delegate void WindowClosedDelegate(object sender, WindowEventArgs args); event WindowClosedDelegate OnClosed; long FormId { get; set; } UIContextClass UIContext { get; set; } IClientForm ParentForm { get; set; } void Window\_Closed(object sender, WindowEventArgs args); }
// Below is the default method implementation
public static class IClientFormHelper { public static void SetUiContext(this IClientForm iClientForm, UIContextClass \_UiContext) { iClientForm.UIContext = \_UiContext; // I put a breakpoint here and it's never hit iClientForm.FormId = \_UiContext.AppContext.ClientGetUniqueFormId(); iClientForm.UIContext.AddForm(iClientForm); iClientForm.OnClosed += iClientForm.UIContext.Window\_Closed; } }
The main problem I see right now is that the default method code never runs. I assume the code is supposed to run as soon as I call the setter for
UIContext
that's declared in the main interface. Apparently, this is something I don't understand. What I want is for every IClientForm window to run the default code whenever the UIContext setter is called for that form, so that each separate window class doesn't need the same code repeated inside of it. Can someone spot what I've done wrong and point me in the right direction? I sincerely appreciate your time.The difficult we do right away... ...the impossible takes slightly longer.
Richard Andrew x64 wrote:
default method in an interface works.
Default interface methods - C# feature specifications | Microsoft Learn[^] "to add methods to an interface in future versions without breaking source or binary compatibility with existing implementations of that interface." The feature is a hack which should be avoided if possible. It does not fit your case. An abstract class is a better starting point for your example.
-
Richard Andrew x64 wrote:
default method in an interface works.
Default interface methods - C# feature specifications | Microsoft Learn[^] "to add methods to an interface in future versions without breaking source or binary compatibility with existing implementations of that interface." The feature is a hack which should be avoided if possible. It does not fit your case. An abstract class is a better starting point for your example.
Thanks for your advice.
The difficult we do right away... ...the impossible takes slightly longer.
-
I'm having trouble getting my mind around how a default method in an interface works. Picture the below interface and default method implementation:
public interface IClientForm { delegate void WindowClosedDelegate(object sender, WindowEventArgs args); event WindowClosedDelegate OnClosed; long FormId { get; set; } UIContextClass UIContext { get; set; } IClientForm ParentForm { get; set; } void Window\_Closed(object sender, WindowEventArgs args); }
// Below is the default method implementation
public static class IClientFormHelper { public static void SetUiContext(this IClientForm iClientForm, UIContextClass \_UiContext) { iClientForm.UIContext = \_UiContext; // I put a breakpoint here and it's never hit iClientForm.FormId = \_UiContext.AppContext.ClientGetUniqueFormId(); iClientForm.UIContext.AddForm(iClientForm); iClientForm.OnClosed += iClientForm.UIContext.Window\_Closed; } }
The main problem I see right now is that the default method code never runs. I assume the code is supposed to run as soon as I call the setter for
UIContext
that's declared in the main interface. Apparently, this is something I don't understand. What I want is for every IClientForm window to run the default code whenever the UIContext setter is called for that form, so that each separate window class doesn't need the same code repeated inside of it. Can someone spot what I've done wrong and point me in the right direction? I sincerely appreciate your time.The difficult we do right away... ...the impossible takes slightly longer.
I may not understand fully, but perhaps something like this?
public interface IMyInterface
{
static IMyInterface Instance = new MyStruct();
int Number { get; set; }
}
record struct MyStruct(int Number) : IMyInterface
{}
Then you can use it like this
public void DoWork()
{
IMyInterface myInterface = IMyInterface.Instance;
myInterface.Number = 500;
Console.WriteLine(myInterface.Number);
} -
I'm having trouble getting my mind around how a default method in an interface works. Picture the below interface and default method implementation:
public interface IClientForm { delegate void WindowClosedDelegate(object sender, WindowEventArgs args); event WindowClosedDelegate OnClosed; long FormId { get; set; } UIContextClass UIContext { get; set; } IClientForm ParentForm { get; set; } void Window\_Closed(object sender, WindowEventArgs args); }
// Below is the default method implementation
public static class IClientFormHelper { public static void SetUiContext(this IClientForm iClientForm, UIContextClass \_UiContext) { iClientForm.UIContext = \_UiContext; // I put a breakpoint here and it's never hit iClientForm.FormId = \_UiContext.AppContext.ClientGetUniqueFormId(); iClientForm.UIContext.AddForm(iClientForm); iClientForm.OnClosed += iClientForm.UIContext.Window\_Closed; } }
The main problem I see right now is that the default method code never runs. I assume the code is supposed to run as soon as I call the setter for
UIContext
that's declared in the main interface. Apparently, this is something I don't understand. What I want is for every IClientForm window to run the default code whenever the UIContext setter is called for that form, so that each separate window class doesn't need the same code repeated inside of it. Can someone spot what I've done wrong and point me in the right direction? I sincerely appreciate your time.The difficult we do right away... ...the impossible takes slightly longer.
There different types of `interface` in C#. One is the `IInterface`, which is like the "interface is a contract" idea. ```cs class Foo : IBar{} ``` Another is the "Port Interface" ```cs class Foo { private int FooData1, FooData2; public interface Port { public const String Name = ""; public static ValueType Action(){ return (FooData1, FooData2); } } } ``` In the second case the `interface` is basically a lightweight static class (it even has constructors). Default implementations fall in between, sort of. Default implementations are like virtual methods. If you realize an `IInterface` that has default implementation and do not realize the operation, it will do something similar to the second case. But it places the method on the object and not on an inner interface. If the operation is realized it's like an auto-override of the default virtual implementation. Another difference is that the default implementation methods are instance and the `interface` methods are static.
-
There different types of `interface` in C#. One is the `IInterface`, which is like the "interface is a contract" idea. ```cs class Foo : IBar{} ``` Another is the "Port Interface" ```cs class Foo { private int FooData1, FooData2; public interface Port { public const String Name = ""; public static ValueType Action(){ return (FooData1, FooData2); } } } ``` In the second case the `interface` is basically a lightweight static class (it even has constructors). Default implementations fall in between, sort of. Default implementations are like virtual methods. If you realize an `IInterface` that has default implementation and do not realize the operation, it will do something similar to the second case. But it places the method on the object and not on an inner interface. If the operation is realized it's like an auto-override of the default virtual implementation. Another difference is that the default implementation methods are instance and the `interface` methods are static.
It may be worth pointing out that as the code stands Port interface has no access to FooData1 or FooData2.
public class Foo : Foo.Port
{
private Foo() { }
public int FooData1 { get; set; }
public int FooData2 { get; set; }
public interface Port
{
static Port Default = new Foo();
protected int FooData1 { get; }
protected int FooData2 { get; }
static (int, int) Action()
{
return (Default.FooData1, Default.FooData2);
}
}
}Now we have access to FooData1 and FooData2. Foo is private and the only instance of Foo or Port is Foo.Port.Default and we can access it as such.
var bar = Foo.Port.Default;
var foobar = (Foo)bar;
foobar.FooData1 = 10;
foobar.FooData2 = 20;
Console.WriteLine(Foo.Port.Action());If we want more than the single instance of Foo we need a Clone() method in Foo which can be easily done like this.
public object Clone()
{
var (X, Y) = Foo.Port.Action();
return new Foo()
{
FooData1 = X,
FooData2 = Y
};
}