对我来说,它看起来像编译器错误或一些奇怪的行为.编译器无法确定泛型类中的泛型参数类型
码
public interface IHamster
{
int Some { get; set; }
}
public abstract class BaseHamster : IHamster
{
public int Some { get; set; }
}
public class DerivedHamster : BaseHamster
{
}
class ApplyHitHamster<T> where T : IHamster // <-- same constraint
{
void Zu()
{
BaseHamster hamster = null;
var derived = new DerivedHamster();
IHamster i = derived;
var s = new TakeDamageHamster<T>(i); // <<<< Compilation Error on any variables(hamster,derived,i) WHY?????????
var s2 = new TakeDamageHamster<IHamster>(i); // <<<< But THIS works well
}
}
class TakeDamageHamster<T> where T : IHamster // <-- same constraint
{
public TakeDamageHamster(T Hamster)
{
Console.WriteLine(Hamster.Some);
}
}
Run Code Online (Sandbox Code Playgroud)
如何使用<T>相同的where约束而不是<IHamster>直接约束?
如果两个类具有相同的where T : IHamster 约束,为什么编译器不能确定类型?
编辑: 另一个简化的例子:
public class BaseHamster
{
public int Some { get; set; }
}
public class DerivedHamster : BaseHamster
{
}
class ApplyHitHamster<T> where T : BaseHamster, new() // <-- same constraint
{
void Zu()
{
BaseHamster hamster = new BaseHamster();
var derived = new DerivedHamster();
var s = new TakeDamageHamster<T>();
s.Method(hamster); // <<<< Compilation Error on any variables(hamster,derived) WHY?????????
}
}
class TakeDamageHamster<T> where T : BaseHamster, new() // <-- same constraint
{
public void Method(T hamster)
{
Console.WriteLine(hamster.Some);
}
}
Run Code Online (Sandbox Code Playgroud)
另一个例子:
public class BaseHamster
{
public int Some { get; set; }
}
class ApplyHitHamster<T> where T : BaseHamster, new() // MSDN:
{
void Zu()
{
var hamster = new BaseHamster();
SuperMethod(hamster); // <<<< WTF? T is ALWAYS BaseHamster!!!
SuperMethod(hamster as T);
}
void SuperMethod(T x)
{
}
}
Run Code Online (Sandbox Code Playgroud)
如何使它工作?
1.什么你可以做,使之工作丢给T.
BaseHamster hamster = null;
var derived = new DerivedHamster();
T i = derived as T;
var s = new TakeDamageHamster<T>(i);
Run Code Online (Sandbox Code Playgroud)
但是,您还需要添加class约束.
class ApplyHitHamster<T> where T : class, IHamster
{
// Other stuff..
}
Run Code Online (Sandbox Code Playgroud)
2.或者,您可以更改构造函数以使用该接口.那也行.
class TakeDamageHamster<T> where T : IHamster
{
public TakeDamageHamster(IHamster Hamster)
{
Console.WriteLine(Hamster.Some);
}
}
Run Code Online (Sandbox Code Playgroud)
3.或者你可以使用new T().请记住,这也需要您添加new()约束.
BaseHamster hamster = null;
var derived = new T();
var s = new TakeDamageHamster<T>(derived); // <<<< Compilation Error on any variables(hamster,derived,i) WHY?????????
var s2 = new TakeDamageHamster<IHamster>(derived); // <<<< But THIS works well
Run Code Online (Sandbox Code Playgroud)
为什么它不起作用?
因为约束并不能保证i实际上是从中派生出来的T.假设我们创建了一个AnotherHamster.请注意,它继承自BaseHamster但不是从DerivedHamster.
public class DerivedHamster : BaseHamster
{
}
public class AnotherHamster : BaseHamster
{
}
Run Code Online (Sandbox Code Playgroud)
现在我们创建一个实例ApplyHitHamster.
var fooHamster = new ApplyHitHamster<AnotherHamster>();
fooHamster.Zu(); // Let's pretend that the method is public. :)
Run Code Online (Sandbox Code Playgroud)
这将最终尝试创建一个实例TakeDamageHamster<AnotherHamster>.但是等等,你正试图发送一个DerivedHamster它的构造函数.
BaseHamster hamster = null;
var derived = new DerivedHamster();
IHamster i = derived;
// You cannot send DerivedHamster when it expects AnotherHamster.
var s = new TakeDamageHamster<T>(i); // T is now AnotherHamster.
Run Code Online (Sandbox Code Playgroud)
请记住,这i是一个DerivedHamster,但TakeDamageHamster<AnotherHamster>期望一个AnotherHamster.因此它不编译.
另一个例子.假设你像这样初始化你的类:
var fooHamster = new ApplyHitHamster<BaseHamster>();
fooHamster.Zu();
Run Code Online (Sandbox Code Playgroud)
现在T是BaseHamster.这将使代码看起来像这样:
var derived = new DerivedHamster();
IHamster i = derived;
var s = new TakeDamageHamster<BaseHamster>(i); // Cannot pass IHamster when ctor expects BaseHamster.
Run Code Online (Sandbox Code Playgroud)
它不会编译,因为TakeDamageHamster期望一个BaseHamster(或从它派生的东西)作为它的构造函数的参数.但你发送的是IHamster.即使是BaseHamster工具,它们也不是一样的东西IHamster.IHamster不是源于BaseHamster.
有可能是其他几个实现IHamster,这并不会从派生BaseHamster.并且你的代码不应该因为IHamster创建另一个实现而破坏,对吧?所以编译器不允许这样做,因为你的constaint不限制它.
| 归档时间: |
|
| 查看次数: |
150 次 |
| 最近记录: |