2017-08-02 99 views
1

我是C#的新手,尝试将差异限制应用于模板类型时遇到了一些实际问题。也许这是不可能的,我可以从我的研究中找到的唯一的“Where”子句更多地基于走向另一个方向(即“可分配来自”)。我列出了我试图效仿的Scala函数 - 关键是要确保T可分配给U(即T <:U),所以无论如何返回值都是U.任何帮助或C#方差提示理解,谢谢你从Scala的选项C#方差返回类型

interface Option<out T> // where T : class 
    { 
     T GetUnsafe(); 
     Option<X> map<X>(Func<object,Option<X>> f); 
     U GetOrElse<U>(U u) where T:U ; //What is wrong here,how do I get U:>T ? 

     bool IsSome { get; } 
    } 

实施例[A] 最终DEF getOrElse [B>:A](默认值:⇒B):乙

作为更新,这里有一个工作版本的静态函数 - 我只是无法弄清楚是否有可能作为一种方法

static class Option 
    { 
     public static U GetOrElse<T, U>(Option<T> o, U defAns) where T : U 
     { 
      if (o.IsSome) return o.GetUnsafe(); else return defAns; 
     } 
+1

为了这个工作,你需要在界面而不是方法上声明'U'。 – juharr

+0

如前所述,方差仅适用于接口的类型参数。无论如何,你想要的方法的约束是无效的(你只能约束方法的类型参数继承一些类)。这就是说,恕我直言,有这样的方法是一个尴尬的设计。为什么这个方法不能返回'T'?对于有'Option '的人来说,用一个类型参数调用一个方法'GetorElse ()'可能只会是'T'的一个基类型,对于一个有什么好处呢?你的问题看起来很像[XY问题](https://meta.stackexchange.com/questions/66377/what-is-the-xy-problem)。 –

+0

@PeterDuniho我知道这可能看起来很奇怪,但这不是我的发明,scala完全是这样。这里有一个例子说明为什么U需要这样绑定 - 比如说这个对象是一些,但是现在它已被上传到我的代码中处理选项的地方,而没有知道任何内容。我在那个时候发出的电话必须确保U是内部项目的超类型,否则将是完全错误的。 Var Cat = myCat.getOrElse(new Cat)..如果它没有界限:Var Cat = myCat.getOrElse(123455)将是一个问题 – LaloInDublin

回答

1

首先你似乎与“泛型类型约束”混合“通用方”。是的,与Java或Scala不同的C#在一个方向上仅支持继承相关的类型约束:您可以指定基类(但您可以执行Scala或Java支持,例如new约束)。有关详细信息,请参见where (generic type constraint) (C# Reference)。并且由于T在外部作用域中定义,所以不能在内部作用域中对其添加其他约束。这就是你的例子不能编译的原因。第二个使用静态方法的示例编译,因为C#编译器足够聪明,可以在声明中重新排序泛型类型,使其看起来像使用已知类型(U)定义约束(对于T)。

我不知道什么是getOrElse Scala的方法是设计鉴于Option是协也就是说,如果你想获得B类型的值,即使它的实际类型A刚刚宣布你var的现实生活中的使用因为型号为Option[B]。所以我认为不复制这一点逻辑不是一大损失。

通常我不认为您可以轻松地复制这样的代码,从Scala保留到C#的行为,但对于此方法只有一个您不需要重写的固定实现的特定情况,您可以扩展您静态招用extension methods

public static class OptionHelper 
{ 
    public static U GetOrElse<T, U>(this Option<T> o, U defAns) 
     where T : U 
    { 
     if (o.IsSome) return o.GetUnsafe(); else return defAns; 
    } 
} 

因为额外this关键字的参数,然后才能使用它,就好像它在接口本身定义(类似于一个位中的默认的Java 8的方法,你可以得到使用隐含了什么转换在斯卡拉):

Option<string> o = ..; 
object value = o.GetOrElse(new object()); 
+0

谢谢,看起来静态函数是解决这些问题的最佳方法 – LaloInDublin