TE
TechEcho
Home24h TopNewestBestAskShowJobs
GitHubTwitter
Home

TechEcho

A tech news platform built with Next.js, providing global tech news and discussions.

GitHubTwitter

Home

HomeNewestBestAskShowJobs

Resources

HackerNews APIOriginal HackerNewsNext.js

© 2025 TechEcho. All rights reserved.

C# almost has implicit interfaces

53 pointsby mwsherman10 months ago

14 comments

g15jv2dp10 months ago
So if I declare a couple of methods named &quot;Foo&quot; and &quot;Bar&quot;, and someone somewhere declares an interface FooBar consisting of those two method names - and bad luck, same signature - then I have to make sure I follow the semantics of that interface I might not even know about, because even if I don&#x27;t declare it so, anyone could use my class and push it through the FooBar-shaped hole. That&#x27;s absurd.<p>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&#x27;s A code and the interface from person B&#x27;s code without realizing.
评论 #41076026 未加载
评论 #41075673 未加载
评论 #41076039 未加载
评论 #41075665 未加载
评论 #41076261 未加载
评论 #41076903 未加载
评论 #41075923 未加载
评论 #41076041 未加载
评论 #41076155 未加载
评论 #41076386 未加载
JTyQZSnP3cQGa8B10 months ago
I always wondered how that would work in a medium or large codebase.<p>Is it easy to refactor? Refactoring can change the interface of classes, which is easier if they are explicit.<p>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.<p>Not knowing explicitly whether I can use an object or not is confusing, or am I missing something obvious?<p>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.
评论 #41075622 未加载
评论 #41075446 未加载
评论 #41075508 未加载
评论 #41076647 未加载
banashark10 months ago
F# has an interesting way to achieve a similar function in Statically Resolved Type Parameters (SRTP)<p>Palatable blog post: <a href="https:&#x2F;&#x2F;www.compositional-it.com&#x2F;news-blog&#x2F;static-duck-typing-in-f&#x2F;" rel="nofollow">https:&#x2F;&#x2F;www.compositional-it.com&#x2F;news-blog&#x2F;static-duck-typin...</a><p>Official docs: <a href="https:&#x2F;&#x2F;learn.microsoft.com&#x2F;en-us&#x2F;dotnet&#x2F;fsharp&#x2F;language-reference&#x2F;generics&#x2F;statically-resolved-type-parameters" rel="nofollow">https:&#x2F;&#x2F;learn.microsoft.com&#x2F;en-us&#x2F;dotnet&#x2F;fsharp&#x2F;language-ref...</a>
评论 #41076880 未加载
评论 #41076182 未加载
kevingadd10 months ago
In general, problems that some languages would solve with an interface containing 1-2 methods can be solved simply via delegates in C#. Then you can bind to any method with a compatible signature, or to an anonymous closure, or to a local function, without any fuss. Compared to the bad old days of having to write a whole anonymous class in java, it&#x27;s pretty straightforward. Thankfully things like ValueTuple are built-in now alongside ref&#x2F;out parameters, so producing multiple return values is no problem.<p>The downside is usually a method with a compatible signature doesn&#x27;t have compatible behavior. This is part of why explicit interfaces are still valuable.
tgma10 months ago
That&#x27;s a single function pointer not an interface which is a named set of function pointers.
评论 #41076387 未加载
beart10 months ago
I&#x27;m a bit surprised by the comments here. Isn&#x27;t this just duck typing, which has been a thing in dynamic languages for a very long time?<p>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.<p>I&#x27;ve worked in c# and typescript. I don&#x27;t think this feature is particularly needed in c#, but I also don&#x27;t see the issues presented by other comments as real problems.
评论 #41076310 未加载
swisniewski10 months ago
Extension methods complicate implicit interfaces considerably.<p>This is likely one of the reason they don’t exist in C#.<p>It’s also one of the reasons GO doesn’t have extension methods.<p><a href="https:&#x2F;&#x2F;github.com&#x2F;golang&#x2F;go&#x2F;issues&#x2F;37742#issuecomment-596167605">https:&#x2F;&#x2F;github.com&#x2F;golang&#x2F;go&#x2F;issues&#x2F;37742#issuecomment-59616...</a><p>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.<p>For that reason, its unlikely you would see this in C#.<p>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.<p>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.<p>If you eliminate extension methods it’s much easier to add dynamic interfaces.
UglyToad10 months ago
I&#x27;ve been experimenting with this, it makes testing trivial and removes the coupling that inevitably occurs with multi method interfaces.<p>However I think there&#x27;s one missing enhancement that would turn it from esoteric and difficult to reason about to actually usable that the language will never get.<p>This is being able to indicate a method implements a delegate so that compilation errors and finding references work much more easily.<p>E.g. suppose you have:<p><pre><code> delegate Task&lt;string&gt; GetEntityName(int id) public async Task&lt;string&gt; MyEntityNameImpl(int id) </code></pre> I&#x27;d love to be able to mark the method:<p><pre><code> public async Task&lt;string&gt; MyEntityNameImpl(int id) : GetEntityName </code></pre> 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.
评论 #41079552 未加载
SideburnsOfDoom10 months ago
In other words: an interface with one member is equivalent to a function reference.<p>There is an equivalence between public interface IThingDoer { int DoTheThing(int value); } and Func&lt;int, int&gt; doTheThing.<p>Converting from one to the other is left as an exercise to the reader.
chris_wot10 months ago
Isn&#x27;t this just a peculiar brand of parameterized type?
agumonkey10 months ago
So it&#x27;s a kind of interface narrowing ?
cryptonector10 months ago
&gt; I though it was clever, and I was a bit enamored when I first heard it (having come from a C# background). Now, I think implicit interfaces are simply, obviously right.<p>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.
issafram10 months ago
Eh I don&#x27;t see the need for it. Explicit is the way to do. The biggest mistake they&#x27;ve made in recent memory was adding default implementations of interfaces. Makes no sense.
评论 #41076122 未加载
WhereIsTheTruth10 months ago
You can in D<p><pre><code> struct Foo { void read(){} } struct Bar { void read(){} } struct Nope { } void handle(T)(T data) { static if (__traits(hasMember, data, &quot;read&quot;) == false) static assert(0, &quot;struct needs a &#x27;read&#x27; function&quot;); data.read(); } void main() { Foo foo; Bar bar; Nope nope; handle(foo); &#x2F;&#x2F; works handle(bar); &#x2F;&#x2F; works handle(nope); &#x2F;&#x2F; oops main.d(17): Error: static assert: &quot;struct needs a &#x27;read&#x27; function&quot; }</code></pre>