【问题标题】:Generic interface constraint通用接口约束
【发布时间】:2013-11-20 10:13:42
【问题描述】:

我有一个关于泛型和在创建具体类时使用接口转换的问题:


namespace MyNamespace
{
    interface ITest
    {

    }

    class Timpl : ITest
    {

    }

    class Test<T> where T : ITest
    {
        public T get()
        {
            return default(T);
        }
    }

    class MyClass
    {
        public MyClass()
        {
            Test<ITest> s = new Test<Timpl>(); //Does not compile
        }
    }
}

我阅读了协变和逆变,但我一定遗漏了一些东西,或者它与我正在尝试做的事情无关,或者它只是对我正在尝试做的事情不起作用。

虽然我可以在 Test 之间进行转换,因为 TImple 继承自 ITest。

【问题讨论】:

  • 您没有发现所提供的任何答案有用吗?不要忘记通过检查答案分数下方的绿色标记将其标记为已接受。

标签: c# generics interface casting


【解决方案1】:

应该是

class Test<T> where T : ITest
{
    public T get()
    {
        return default(T);
    }
}

然后创建Testlike的实例

var s = new Test<Timpl>();

编辑:

根据下面的评论。好的,现在您正在处理协变和逆变。如果需要指定

Test<ITest> s = new Test<Timpl>();

那么它就不能工作了,因为只有接口和委托的泛型类型参数可以标记为协变或逆变。

但是,您可以通过使Test 实现一个接口来解决它。

interface ITestClass<out T>
{
    T get();
}

class Test<T> : ITestClass<T> where T : ITest
{
    public T get()
    {
        return default(T);
    }
}

ITestClass<ITest> s = new Test<Timpl>(); // Does compile

【讨论】:

  • 对不起,但没有注意到它没有写greaterthen和lessthen标签。所以这个例子现在有点不同了。
【解决方案2】:

试试这个。

namespace MyNamespace
{
    interface ITest
    {
    }

    class Timpl : ITest
    {
    }

    class Test<T> where T : ITest
    {
        public T get()
        {
            return default(T);
        }
    }

    public class mycls : ITest
    {
    }

    class MyClass
    {
        public MyClass()
        {
            Test<mycls> s = new Test<mycls>(); //will compile
        }
    }
}

【讨论】:

  • 当 OP 已经实现了 ITest 时,为什么还要创建 mycls?看来他只是不知道怎么用。
  • 对不起,但没有注意到它没有写greaterthen和lessthen标签。所以这个例子现在有点不同了。
【解决方案3】:

我想我理解你的问题。您可以通过以下 MSDN 链接了解协变和逆变:http://msdn.microsoft.com/en-us/library/vstudio/ee207183.aspx

我对您问题的解决方案如下所示

接口 ITest { }

class TImpl:ITest
{

}

interface ITest<out T>
{
    T get();
}

class Test<T>:ITest<T> 
          where T:ITest
{
    public T get()
    {
        return default(T);
    }
}

如您所见,我在您的 Test 类上添加了接口,并将 Type 参数 T 标记为 out。现在您可以执行以下操作:

 ITest<ITest> t = new Test<TImpl>();

希望对你有帮助

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-08-28
    • 2011-01-13
    • 1970-01-01
    • 2010-10-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多