我在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();
一切都很好。
有人可以解释一下我的错误以及为什么最终会编译代码吗?
谢谢。
答案 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
的关系。
因此:
Class1
的超类,而且Class1
也可能不是T =&gt;的超类; Class1
失败(T)GetInstanceOfClass1()
IInterface
失败有效的那个:
您当然可以将(IInterface1)GetInstanceOfClass1()
转换为Class1
因为IInterface
实现了接口。
现在,由于T还实现了IInterface,它可能是一个有效的强制转换,或者它可能在运行时失败。
这与在编译时将任何对象转换为给定类型的方式类似,但如果对象的运行时类型错误,则会在运行时失败。
E.g。
Class1
这是编译,但在运行时失败。