gpt4 book ai didi

java - 在 C# 中存储泛型类型引用

转载 作者:太空宇宙 更新时间:2023-11-03 19:51:27 24 4
gpt4 key购买 nike

我正在将我的一些 Java 代码移植到 C#,但我无法复制此行为:

***** JAVA 代码 *****

public abstract class Fruit<T extends Fruit>{
//Fruit implementation
}

这很棒,因为我只想要扩展 Fruit 的泛型类型。然后我可以像这样存储所有具体水果对象的引用:

Banana banana = new Banana(); //This class extends Fruit
Strawberry strawberry = new Strawberry (); //This class extends Fruit

Fruit fruit;
fruit = banana;
//or
fruit = strawberry;

这很好用。现在我在 C# 中尝试相同的方法,并且 Fruit 类声明如下:

***** C# 代码 *****

abstract public class Fruit<T> where T : Fruit<T> {
//Fruit implementation
}

但在 C# 中,我不能存储这样的引用:

Fruit fruit; //This gives a compilation error!

我无法将香蕉和草莓存储在同一个引用中,我只能这样做:

Fruit<Banana> fruit;
fruit = banana;
//or
Fruit<Strawberry> fruit;
fruit = strawberry;

我想我可以通过添加这样的继承级别来解决这个问题:

abstract public class GenericFruit<T> where T : GenericFruit<T> {}

然后创建等效的 Fruit 类

abstract public class Fruit : GenericFruit<Fruit>{}

现在像这样从 Fruit 扩展 Banana 和 Strawberry:

public class Banana : Fruit {}
public class Strawberry : Fruit {}

然后存储一个 Fruit 引用:

Fruit fruit;
fruit = new Banana();
fruit = new Strawberry();

但这有点像作弊:(有什么想法吗?我做错了什么吗?

最佳答案

您遇到的问题是您试图“忘记”(或删除)您创建的一些类型信息。让我们通过向基类添加一个方法来使示例更具体一些:

public abstract class Fruit<T> where T : Fruit<T>
{
public abstract T GetSeedless();
}

好的,现在让我们更仔细地看看您要做什么。让我们假设你可以做你想做的事并且你有一个水果篮:

Fruit fruit = new Apple();
var seedlessFruit = fruit.GetSeedless();

好的,seedlessFruit 的类型是什么? ?您可能倾向于说它是 Fruit这是合理的,但 C# 不允许这样做。 C# 不允许您删除类的泛型参数。当你声明 Fruit<T>你谴责所有Fruit有一个通用参数,你不能删除它。

我认为您已接近解决方案,但我认为您的解决方案有点颠倒。而不是拥有非通用的 Fruit继承自 GenericFruit<Fruit> ,你应该翻转它并让通用版本从非通用版本继承。

我还有另一个建议,那就是制作非通用的 Fruit进入接口(interface)而不是抽象类。我将说明原因(归根结底,这是因为 C# 在覆盖方法时不允许返回类型协变;可以肯定的是,这很糟糕)。

public interface IFruit
{
IFruit GetSeedless();
}

public abstract class Fruit<T> : IFruit where T : Fruit<T>
{
public abstract T GetSeedless();

IFruit IFruit.GetSeedless()
{
return GetSeedless();
}
}

我在这里所做的是通过显式实现 IFruit 创建了一个假的返回类型协方差。 Fruit 中的界面类(class)。这现在允许您在同一个引用中存储不同种类的水果,并且仍然使用 GetSeedless方法:

IFruit fruit = new Apple();
var seedlessFruit = fruit.GetSeedless();

这还允许您在要删除通用信息时挑选和选择哪些方法和属性应该可用。这些方法中的每一个都可以在基类中显式实现,并用通用版本“替换”。这样,如果您确实拥有通用类型信息,就可以使用更具体的类型。

关于java - 在 C# 中存储泛型类型引用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38743149/

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