MethodA
在Argument 1: cannot convert from 'Callback<T>' to 'Callback<SomeBaseClass>' [Assembly-CSharp]
Callback<T> theInstance
:
Callback<T>
但是MethodD可以很好地将其实例传递给MethodE
当我指定T扩展SomeBaseClass
的约束时,为什么我不能将MethodA中的泛型Callback<SomeBaseClass>
实例传递给MethodB中类型{{1}}的参数
答案 0 :(得分:4)
基本上,你不能这样做,因为它不安全。
假设我们有一个派生自SomeBaseClass
的具体类:
public class SomeOtherSpecificClass {}
假设我们将您的MethodB
更改为:
void MethodB(Callback<SomeBaseClass> theInstance)
{
theInstance(new SomeOtherSpecificClass());
}
应该编译,对吗?毕竟,您只是将SomeOtherSpecificClass
传递给Callback<SomeBaseClass>
,这应该没问题。
然后,如果我这样打MethodA
:
Callback<SomeSpecificClass> callbcak = data => Console.WriteLine(data.propertyA);
MethodA(callback);
...如果所有这些都被允许,我们会将SomeOtherSpecificClass
传递给期望SomeSpecificClass
的委托。
您的MethodD
和MethodE
示例很好,因为MethodE
只能使用SomeBaseClass
的成员...但Callback<SomeSpecificClass>
确实要求 SomeSpecificClass
,因此您不能将其视为接受SomebaseClass
的方法。
更简单地展示:
// This is valid...
string text = "";
object obj = text;
// This isn't...
Action<string> stringAction = text => Console.WriteLine(text.Length);
Action<object> objectAction = stringAction;
// ... because it would allow this:
objectAction(new object());
答案 1 :(得分:3)
不允许这样做,因为您要执行非法分配。如果允许,那意味着你可以作为基类的参数实例传递给方法,实际需要继承类的实例:
Action<TChild> source;
Action<TBase> target;
//your intention:
target = source;
//will be compiled, but as it actual "source", that needs childInstance, not baseInstance,
//it is illegal
target(baseInstance);
您可以尝试修复它或通过逆转来清楚地理解(在关键字中):
public delegate void Callback<in T>(T data);
void MethodA(Callback<SomeBaseClass> theInstance)
{
MethodB(theInstance);
}
void MethodB<T>(Callback<T> theInstance) where T : SomeBaseClass
{
}
法律使用:
Action<TBase> source;
Action<TChild> target;
//your intention:
target = source;
//will work, because it is actual "source", that needs TBase or inherited types like TChild
target(childInstance);