C#类型推断,泛型和接口

时间:2015-10-06 07:35:58

标签: c#

我在C#中的类型推断中发现了一些奇怪的东西。

示例。

我有一个界面

interface IInterface1
{
}

和实现接口的类

class Class1 : IInterface1
{
}

然后我有一个创建类

的函数
static Class1 GetInstanceOfClass1()
{
    return new Class1();
}

我想使用将返回可枚举

的泛型函数
static IEnumerable<T> GetSomething<T>() where T : IInterface1
{
    yield return GetInstanceOfClass1();
}

完整的代码是

using System.Collections.Generic;

namespace TypeInference
{
    interface IInterface1
    {
    }

    class Class1 : IInterface1
    {
    }

    class Program
    {
        static Class1 GetInstanceOfClass1()
        {
            return new Class1();
        }

        static IEnumerable<T> GetSomething<T>() where T : IInterface1
        {
            yield return GetInstanceOfClass1();
        }

        static void Main(string[] args)
        {
        }
    }
}

此代码未编译

  

无法将类型'TypeInference.Class1'隐式转换为'T'

如果我写为

yield return (T)GetInstanceOfClass1();

错误消息为

  

无法将类型'TypeInference.Class1'转换为'T'

它无法像以前一样转换。

确定。我写的是

yield return (IInterface1)GetInstanceOfClass1();

得到了

  

无法将类型'TypeInference.IInterface1'隐式转换为'T'

它无法像以前一样转换。

但如果我写作

yield return (T)(IInterface1)GetInstanceOfClass1();

一切都很好。

有人可以解释一下我的错误以及为什么最终会编译代码吗?

谢谢。

2 个答案:

答案 0 :(得分:8)

防止自己在脚下射击自己。就像你设法最终做到的那样。

如果定义

会发生什么
interface IInterface2 : IInterface1 { }

然后拨打GetSomething<IInterface2>()?它是一个有效的泛型类型参数,但Class1并未实现IInterface2

更糟糕的是,如果你定义

会发生什么
class Class2 : IInterface1 { }

然后拨打GetSomething<Class2>()

您的设计已被破坏,您需要更多地考虑它,而不是继续解决编译器错误,直到您的设计实际上有可能工作。

答案 1 :(得分:3)

您的类型参数T保证实现<?xml version="1.0" encoding="UTF-8" ?> <Button xmlns:android="http://schemas.android.com/apk/res/android" xmlns:local="http://schemas.android.com/apk/res-auto" android:layout_height="wrap_content" android:layout_width="wrap_content" android:text="Navigate to 2" local:MvxBind="Click NavigateCommand" /> ,但未指定与IInterface1的关系。

因此:

  1. T可能不是Class1的超类,而且Class1也可能不是T =&gt;的超类; Class1失败
  2. 您无法从返回T =&gt;的方法返回(T)GetInstanceOfClass1() IInterface失败
  3. 有效的那个:

    您当然可以将(IInterface1)GetInstanceOfClass1()转换为Class1因为IInterface实现了接口。 现在,由于T还实现了IInterface,它可能是一个有效的强制转换,或者它可能在运行时失败。 这与在编译时将任何对象转换为给定类型的方式类似,但如果对象的运行时类型错误,则会在运行时失败。

    E.g。

    Class1

    这是编译,但在运行时失败。