C#是否与Scala的结构类型相当?

在Scala中,我可以定义结构类型如下:

type Pressable = { def press(): Unit }

这意味着我可以定义一个函数或方法,它将一个可压缩的参数作为参数,如下所示:

def foo(i: Pressable) { // etc.

我传递给这个函数的对象必须为它定义一个名为press()的方法,它匹配类型中定义的类型签名 – 不带参数,返回Unit(Scala的void版本)。

我甚至可以使用结构类型内联:

def foo(i: { def press(): Unit }) { // etc.

它基本上允许程序员拥有鸭子打字的所有好处,同时仍然具有编译时类型检查的好处。

C#有类似的东西吗? 我用谷歌搜索但找不到任何东西,但我不熟悉C#的任何深度。 如果没有,有没有计划添加这个?

不,我也不知道。 仅命名(而不是结构)子类型(例如接口)。

(其他人可能也希望看到

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

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

(有些人可能会指出一些异国情调的案例,比如使用结构类型为GetEnumeratorforeach语句,但这是例外而不是规则。)

没有办法定义具有特定function的结构类型。 有一个库可以为C#添加鸭子打字支持,可以在这里找到。

这是Duck Typing项目的例子。 请注意鸭子类型在运行时发生,可能会失败 。 我的理解是,这个库为类型为鸭子的类型生成代理,这与Scala中享受的优雅编译时支持相去甚远。 这很可能与这一代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(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); } } 

这是使用好的无聊接口实现相同function的C#方式。

 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); } } 

正如其他人所指出的,这在.NET中并不真正可用(因为这更像是运行时而不是语言)。 但是,.NET 4.0支持导入的COM接口类似的东西,我相信这可以用于实现.NET的结构类型。 看到这篇博文:

  • 伪造COM来欺骗C#编译器

我自己也没有尝试过这个,但我认为这可能使编译器作者能够编写带有.NET结构类型的语言。 (这个想法是你(或编译器)会在场景后面定义一个接口,但是它会起作用,因为由于COM等价特性,接口会被视为等价的)。

此外,C#4.0支持dynamic关键字,我认为可以将其解释为结构类型(没有静态类型检查)。 该关键字允许您在不知道(在编译时)对象是否具有所需方法的情况下调用任何对象上的方法。 这与Igor提到的“Duck typing”项目基本相同(但当然,这不是一个正确的结构类型)。

C#中的等待模式可能被解释为结构子类型/存在性类型的有限的临时实例。 编译器只会await有权访问GetAwaiter()方法的对象,该方法返回任何带有一组特定方法和属性的INotifyCompletion对象。 由于’awaitable’对象和’awaiter’对象都不需要实现任何接口(在后者的情况下除了INotifyCompletion ), await类似于接受结构类型的等待对象的方法。