Does C# have an equivalent to Scala's structural typing?

痞子三分冷 提交于 2019-11-29 13:24:17

No, and no plans that I know of. Only named (rather than structural) subtyping (e.g. interfaces).

(Others may want to see also

http://en.wikipedia.org/wiki/Nominative_type_system

http://en.wikipedia.org/wiki/Structural_type_system

)

(A few people may point out some exotic corner cases, like the foreach statement using structural typing for GetEnumerator, but this is the exception rather than the rule.)

Igor Zevaka

There isn't a way to define structural types that has a particular function. There is a library that adds duck typing support to C# that can be found here.

This is the example from Duck Typing project. Please note the the duck typing happens at runtime and can fail. It is my understanding also that this library generates proxies for the types that are duck typed, which is far cry from the elegant compile-time support that is enjoyed in Scala. This is most likely as good as it gets with this generation of C#.

public interface ICanAdd
{
    int Add(int x, int y);
}

// Note that MyAdder does NOT implement ICanAdd, 
// but it does define an Add method like the one in ICanAdd:
public class MyAdder
{
    public int Add(int x, int y)
    {
        return x + y;
    }
}

public class Program
{
    void Main()
    {
        MyAdder myAdder = new MyAdder();

        // Even though ICanAdd is not implemented by MyAdder, 
        // we can duck cast it because it implements all the members:
        ICanAdd adder = DuckTyping.Cast<ICanAdd>(myAdder);

        // Now we can call adder as you would any ICanAdd object.
        // Transparently, this call is being forwarded to myAdder.
        int sum = adder.Add(2, 2);
    }
}

This is the C# way of achieving the same thing using the good ol boring interfaces.

interface IPressable {
  void Press();
}

class Foo {
 void Bar(IPressable pressable) {
    pressable.Press();
 }
}

class Thingy : IPressable, IPushable, etc {
 public void Press() {
 }
}

static class Program {
 public static void Main() {
  pressable = new Thingy();
  new Foo().Bar(pressable);
 }
}

As others noted, this is not really available in .NET (as this is more a matter of the runtime than a language). However, .NET 4.0 supports similar thing for imported COM interfaces and I believe this could be used for implementing structural typing for .NET. See this blog post:

I didn't try playing with this myself yet, but I think it might enable compiler authors to write languages with structural typing for .NET. (The idea is that you (or a compiler) would define an interface behind the scene, but it would work, because the interfaces would be treated as equivalent thanks to the COM equivalence feature).

Also, C# 4.0 supports the dynamic keyword which, I think, could be interpreted as a structural typing (with no static type checking). The keyword allows you to call methods on any object without knowning (at compile-time) whether the object will have the required methods. This is essentially the same thing as the "Duck typing" project mentioned by Igor (but that's, of course, not a proper structural typing).

The awaitable pattern in C# can perhaps be interpreted as a limited, ad hoc instance of structural subtyping / existential typing. The compiler will only await objects that have access to a GetAwaiter() method that returns any INotifyCompletion object with a specific set of methods and properties. Since neither the 'awaitable' object nor the 'awaiter' object needs to implement any interface (except INotifyCompletion in the case of the latter), await is similar to a method that accepts structurally typed awaitable objects.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!