gpt4 book ai didi

c# - 有没有办法将泛型类向下转换为具有派生 T 的实例?

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

假设我有以下类用于包装给定类型的一些项目:

public class IndexedModelWithValue<T>
{
public IndexedModelWithValue(T value, int index)
{
Index = index;
InnerValue = value;
}

public int index;

public T InnerValue { get; }
}

我有这两个类:

class Animal { }
class Dog : Animal { }

在某些时候,我加载了不同的对象(这里我们将只使用 Dog 类),它们都继承自相同的基类型,所以我会有这样的东西:

Dog dog = LoadMyDerivedAnimalFromSomewhere();
Animal animal = dog;

// In my actual code I have something like
IEnumerable<Animal> animals = LoadMyDerivedAnimalsFromSomewhere();

然后继续包装所有这些项目,以便我最终得到类似的东西:

IndexedModelWithValue<Animal> indexedAnimal = new IndexedModelWithValue(animal, 0);

现在,我知道索引模型中的动物实际上是 Dog例如,有没有办法以 IndexedModelWithValue<Dog> 结束?来自那个的对象?

我考虑过使用接口(interface)(我不介意以 IIndexedModelWithValue<Dog> 结尾,只要我在其中输入 Dog 类型),但据我了解,协变类只能强制转换在相反的方向(IEnumerable<String>IEnumerable<object,反之亦然),我不能在这里使用逆变类,因为该类公开了 T 参数。

感谢您的帮助!

编辑:为澄清起见,我是这样结束我的列表的:

IEnumerable<Animal> animals = LoadAllMyAnimalsFromSomewhere();
IEnumerable<IndexedModelWithValue<Animal>> = animals.Select((item, i) => new IndexedModelWithValue(item, i));

临时(不良)解决方法:目前我使用的解决方案是向索引类添加一个方法:

public IndexedModelWithValue<TValue> Downcast<TValue>() where TValue : T
{
return new IndexedModelWithValue<TValue>((TValue)InnerValue, Index);
}

这样我就可以做到:

IndexedModelWithValue<Dog> indexedDog = indexedAnimal.Downcast<Dog>();

唯一的问题是这样我创建了一个新的 IndexedModelWithValue 实例每次我调用此方法时都是类(所以我在浪费内存和 CPU 时间),而实际上我只是想将该对象转换为我的派生类型。


解决方案:这是我现在用来解决问题的方法:

public static IEnumerable<ICovariantIndexedModelWithValue<T>> New([NotNull] IEnumerable<T> source)
{
int index = 0;
foreach (T item in source)
{
object instance = Activator.CreateInstance(typeof(IndexedModelWithValue<>).MakeGenericType(item.GetType()), item, index);
yield return (ICovariantIndexedModelWithValue<T>)instance;
index++;
}
}

我可以调用它并传递原始列表以获得协变包装列表,其中每个单独的项目都具有“正确的类型”,具体取决于其派生类型。

界面是这样的:

public interface ICovariantIndexedModelWithValue<out T>
{
int Index { get; }

T InnerValue { get; }
}

最佳答案

你的 indexedDogindexedAnimal是两种不同的类型。不仅仅是你把它们放在不同形状的盒子里,实际的类型是不同的。因此,如果不按原样创建新对象,就无法做到这一点。如果你想避免浪费内存、cpu 或其他任何东西,那么你需要将对象创建为 IndexedModelWithValue<Dog>。首先。如果你知道它绝对是一只狗,那么这就是你应该做的。如果你有明确的狗,那么不要创建 IndexedModelWithValue<Animal>首先,您的问题就会消失。在没有看到创建对象的代码的情况下,很难准确地说出如何做到这一点,但泛型应该允许您创建所需的类型。

关于c# - 有没有办法将泛型类向下转换为具有派生 T 的实例?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43679831/

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