gpt4 book ai didi

c# - 如何为另一个泛型类使用泛型参数类型?

转载 作者:太空狗 更新时间:2023-10-30 00:49:05 25 4
gpt4 key购买 nike

对我来说,这看起来像是编译器错误或一些奇怪的行为。编译器无法确定泛型类中的泛型参数类型

代码

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);
}
}

怎么可能使用<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);
}
}

另一个例子:

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)
{
}
}

最佳答案

如何让它发挥作用?

1.要使其正常工作,您可以做的是将其转换为 T .

BaseHamster hamster = null;
var derived = new DerivedHamster();
T i = derived as T;
var s = new TakeDamageHamster<T>(i);

但是您还需要添加 class约束条件。

class ApplyHitHamster<T> where T : class, IHamster
{
// Other stuff..
}

2. 或者,您可以更改构造函数以改为使用接口(interface)。这也行得通。

class TakeDamageHamster<T> where T : IHamster
{
public TakeDamageHamster(IHamster Hamster)
{
Console.WriteLine(Hamster.Some);
}
}

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

为什么它不起作用?

因为约束不保证 i实际上源自T .假设我们创建了一个 AnotherHamster .请注意,它继承自 BaseHamster , 但不是来自 DerivedHamster .

public class DerivedHamster : BaseHamster
{
}

public class AnotherHamster : BaseHamster
{
}

现在我们创建一个 ApplyHitHamster 的实例.

var fooHamster = new ApplyHitHamster<AnotherHamster>();
fooHamster.Zu(); // Let's pretend that the method is public. :)

这最终会尝试创建一个 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.

记住 iDerivedHamster ,但是 TakeDamageHamster<AnotherHamster>期望一个 AnotherHamster .因此它不编译。

另一个例子。假设您像这样初始化您的类:

var fooHamster = new ApplyHitHamster<BaseHamster>();
fooHamster.Zu();

现在TBaseHamster .这将使代码看起来像这样:

var derived = new DerivedHamster();
IHamster i = derived;
var s = new TakeDamageHamster<BaseHamster>(i); // Cannot pass IHamster when ctor expects BaseHamster.

它不会编译因为TakeDamageHamster期望一个 BaseHamster (或从它派生的东西)作为它的构造函数的参数。但是你给它发送了一个 IHamster .它们不是一回事,尽管 BaseHamster工具 IHamster . IHamster不源自 BaseHamster .

可能 IHamster 有其他几种实现方式,它源自BaseHamster .而且您的代码不应该仅仅因为 IHamster 的另一个实现而中断。是创建的,?所以编译器不允许这样做,仅仅是因为你的约束不限制这一点。

关于c# - 如何为另一个泛型类使用泛型参数类型?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40745133/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com