在Scala中,我可以按如下方式定义structural types:
type Pressable = { def press(): Unit }
这意味着我可以定义一个函数或方法,它将可压缩的东西作为参数,如下所示:
def foo(i: Pressable) { // etc.
我传递给这个函数的对象必须为它定义一个名为press()的方法,该方法匹配类型中定义的类型签名 - 不带参数,返回Unit(Scala的void版本)。
我甚至可以使用结构类型内联:
def foo(i: { def press(): Unit }) { // etc.
它基本上允许程序员获得鸭子类型的所有好处,同时仍然具有编译时类型检查的好处。
C#有类似的东西吗?我用谷歌搜索但找不到任何东西,但我不熟悉C#的任何深度。如果没有,有没有计划添加这个?
答案 0 :(得分:11)
不,我也不知道。仅命名(而不是结构)子类型(例如接口)。
(其他人可能也希望看到
http://en.wikipedia.org/wiki/Nominative_type_system
http://en.wikipedia.org/wiki/Structural_type_system
)
(有些人可能会指出一些异国情调的案例,例如使用foreach
结构类型的GetEnumerator
语句,但这是exception而不是规则。)
答案 1 :(得分:7)
没有办法定义具有特定功能的结构类型。有一个库可以为C#添加鸭子类型支持,可以找到here。
这是Duck Typing项目的例子。请注意 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);
}
}
这是使用良好的无聊接口实现相同目标的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);
}
}
答案 2 :(得分:5)
正如其他人所说,这不是真正在.NET中可用(因为这更像是运行时而不是语言)。但是,.NET 4.0支持导入的COM接口类似的东西,我相信这可以用于实现.NET的结构类型。请参阅此博客文章:
我自己也没有尝试过这个,但我认为这可能使编译器作者能够编写.NET结构类型的语言。 (这个想法是你(或编译器)会在场景后面定义一个接口,但是它会起作用,因为由于COM等价特性,接口会被视为等价的。)
此外,C#4.0支持dynamic
关键字,我认为可以将其解释为结构类型(没有静态类型检查)。该关键字允许您在不知道(在编译时)对象是否具有所需方法的情况下调用任何对象上的方法。这与Igor提到的“Duck typing”项目基本相同(但当然,这不是一个正确的结构类型)。
答案 3 :(得分:1)
C#中的等待模式可能被解释为结构子类型/存在性类型的有限的临时实例。编译器将只有await
个有权访问GetAwaiter()
方法的对象,该方法返回具有一组特定方法和属性的任何INotifyCompletion
对象。由于“等待”和“等待”都没有。对象和“awaiter”#39;对象需要实现任何接口(在后者的情况下除INotifyCompletion
之外),await
类似于接受结构类型的等待对象的方法。