by mwsherman on 7/26/24, 1:12 AM with 71 comments
by g15jv2dp on 7/26/24, 3:34 AM
Exercise: imagine what the semantics of the following signature are: `int Read(string)`. Did everyone get the same answer? And yet, with implicit interfaces, you absolutely need everyone to settle on the same answer. Otherwise, person A could write a class with such a method with answer A in mind, person B could write a library declaring an interface with such a method with answer B in mind, and person C could use the class from person's A code and the interface from person B's code without realizing.
by JTyQZSnP3cQGa8B on 7/26/24, 2:39 AM
Is it easy to refactor? Refactoring can change the interface of classes, which is easier if they are explicit.
And my main fear: how do I know I use the right object? I would tempted to add methods all the time to satisfy the target interface instead of using another object that already satisfies that interface.
Not knowing explicitly whether I can use an object or not is confusing, or am I missing something obvious?
Edit: Last but not least, how do I know my classes implement an interface that could require 5 or 10 methods? I had to do that in Go, and counting and searching the methods was really a waste of time, so much that I had to add comments to explain the interfaces that were implemented in every class.
by banashark on 7/26/24, 3:47 AM
Palatable blog post: https://www.compositional-it.com/news-blog/static-duck-typin...
Official docs: https://learn.microsoft.com/en-us/dotnet/fsharp/language-ref...
by kevingadd on 7/26/24, 2:41 AM
The downside is usually a method with a compatible signature doesn't have compatible behavior. This is part of why explicit interfaces are still valuable.
by tgma on 7/26/24, 2:08 AM
by beart on 7/26/24, 6:33 AM
The supposed risks of breaking the contract by changing the class ring hollow to me. The implicit interface you have created is already public. So how is that any different than changing any other public API? There is no suggestion of an implicit interface over private methods.
I've worked in c# and typescript. I don't think this feature is particularly needed in c#, but I also don't see the issues presented by other comments as real problems.
by swisniewski on 7/26/24, 7:06 AM
This is likely one of the reason they don’t exist in C#.
It’s also one of the reasons GO doesn’t have extension methods.
https://github.com/golang/go/issues/37742#issuecomment-59616...
You either have to exclude extension methods from implicit interface definitions (which can feel very unnatural to consumers) or you get weird behavior with dynamic casts that is very confusing and breaks everything.
For that reason, its unlikely you would see this in C#.
VB tried to do this (implement both extension methods and dynamic interfaces), and ended up cutting dynamic interfaces because the two features don’t play well together.
They are an awesome feature in GO, but it’s hard to add them to C# without a whole lot of very messy design compromises that make it kind of wonky.
If you eliminate extension methods it’s much easier to add dynamic interfaces.
by UglyToad on 7/26/24, 6:50 AM
However I think there's one missing enhancement that would turn it from esoteric and difficult to reason about to actually usable that the language will never get.
This is being able to indicate a method implements a delegate so that compilation errors and finding references work much more easily.
E.g. suppose you have:
delegate Task<string> GetEntityName(int id)
public async Task<string> MyEntityNameImpl(int id)
I'd love to be able to mark the method: public async Task<string> MyEntityNameImpl(int id) : GetEntityName
This could just be removed on compile but it would make the tooling experience much better in my view when you control the delegate implementations and definitions.by SideburnsOfDoom on 7/26/24, 6:54 AM
There is an equivalence between public interface IThingDoer { int DoTheThing(int value); } and Func<int, int> doTheThing.
Converting from one to the other is left as an exercise to the reader.
by chris_wot on 7/26/24, 5:17 AM
by agumonkey on 7/26/24, 7:01 AM
by cryptonector on 7/26/24, 8:22 PM
What, no. No, implicit interfaces are not right. They are a footgun. That you provide some interface needs to be declared. I dislike unnecessary ceremony as much as anyone, but this is necessary ceremony.
by issafram on 7/26/24, 3:13 AM
by WhereIsTheTruth on 7/26/24, 5:22 AM
struct Foo
{
void read(){}
}
struct Bar
{
void read(){}
}
struct Nope
{
}
void handle(T)(T data)
{
static if (__traits(hasMember, data, "read") == false) static assert(0, "struct needs a 'read' function");
data.read();
}
void main()
{
Foo foo;
Bar bar;
Nope nope;
handle(foo); // works
handle(bar); // works
handle(nope); // oops main.d(17): Error: static assert: "struct needs a 'read' function"
}