C#Variance返回类型

时间:2017-08-02 00:36:23

标签: c# scala

我是C#的新手,并且在尝试对模板类型应用方差限制时遇到了一些实际问题。也许它不可能是唯一的&#34; Where&#34;我可以从我的研究中找到的子句例子更多地基于向另一个方向发展(即。&#34;可从&#34;分配)。我已经列出了我试图模拟的Scala函数 - 关键是要确保T可以分配给U(即T <:U),所以无论如何返回值都是U.任何有关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; }
    }

Scala选项示例[A] final def getOrElse [B&gt;:A](默认值:⇒B):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 个答案:

答案 0 :(得分:1)

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

我不确定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中的默认方法以及在Scala中使用隐式转换可以获得的内容):< / p>

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