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

Tom*_*ris 18 c# type-systems scala duck-typing structural-typing

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

type Pressable = { def press(): Unit }

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

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

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

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

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

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

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

Bri*_*ian 11

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

(其他人可能也希望看到

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

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

)

(有些人可能会指出一些奇特的角落案例,比如foreach使用结构类型的声明GetEnumerator,但这是例外而不是规则.)


Igo*_*aka 7

没有办法定义具有特定功能的结构类型.有一个库可以为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<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);
    }
}
Run Code Online (Sandbox Code Playgroud)

这是使用良好的无聊接口实现相同功能的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);
 }
}
Run Code Online (Sandbox Code Playgroud)

  • 当然,如果方法不存在,那么duck-casting库可能会在运行时失败?只是想清楚它不是编译时检查. (3认同)

Tom*_*cek 5

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

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

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

  • 没有静态类型检查会破坏结构类型的目的,即IMO. (3认同)