是否有可能拥有不同结构体的List ?
本文关键字:List 结构体 有可能 拥有 是否 | 更新日期: 2023-09-27 18:02:24
我想做一个List
,我可以把多个不同的结构。问题是我不能给List
模板参数,因为结构没有公分母(并且结构的继承是不可能的)。我的意思是:
struct Apple
{
float roundness;
float appleness;
}
struct Orange
{
float orangeness;
bool isActuallyAMandarin;
}
List<???> fruitBasket;
void Main(string [] args)
{
fruitBasket = new List<???>();
fruitBasket.Add( new Apple());
fruitBasket.Add( new Orange());
}
省略List的template参数,很明显,会导致错误:
Using the generic type 'System.Collections.Generic.List<T>' requires 1 type arguments
有办法做到这一点吗?也许与List
或可能与数组或不同的集合类,不需要类型参数?
编辑:这个问题是关于结构体的,不是关于类的我完全意识到这个问题可以用类和继承来解决,但我只是不能自由地使用类来代替(第三方库问题…)。
有一个类是每个结构的基础:它是Object
,所以你可以把它
List<Object> fruitBasket;
,但它意味着封装列表中的每个结构。还有一种可能是
List<ValueType> fruitBasket;
你可以在这里使用接口!
public interface IFruit {}
Apple : IFruit {...}
Orange : IFruit {...}
List<IFruit> list = new List<IFruit>();
list.Add(new Apple());
list.Add(new Orange());
但是,它仍然会导致装箱操作(接口是引用类型)
没问题。你只需要创建一个对象列表。你可以使用旧式的非泛型数组列表,就像我们在。net 1的早期所做的那样。x,或者一个泛型List。因为object是一切的根。
void Main(string [] args) {
var fruitBasket = new List<Object>();
fruitBasket.Add( new Apple());
fruitBasket.Add( new Orange());
}
或
void Main(string [] args) {
var fruitBasket = new ArrayList();
fruitBasket.Add(new Apple());
fruitBasket.Add(new Orange());
}
把东西从清单里拿出来是另一个问题,但是你没有问,是吗?
虽然你的问题已经得到了回答,我还是建议你去看看StackOverflow的这篇文章。这会让你明白很多事情。
在c#中,您可以使用接口来实现与值类型(结构)的多态性类似的东西,因为您不能直接从结构派生,但您可以使用多个结构类型实现特定的接口。
因此,您可以使用一个接口IFruits,而不是抽象结构Fruit。还没有提到的另一种可能性是定义一个结构,它包含足够的字段来封装任何所需结构可能包含的所有值,以及确定如何解释它们的方法。例如:
struct AppleOrOrange{浮动applenessOrOrangeness;int roundnessOrMandarinness;}
由于对float
的任何操作都不会产生某些位模式,因此可以为橘子和非橘子保留两个位模式,并说如果roundnessOrMandarinness
保持其中一个位模式,则该元素应被视为橘子;如果它保存另一个,则应将值按位转换为float
,并将该元素视为苹果。请注意,在这种特殊情况下,这种方法将大大节省内存需求,而不是将所有内容打包(打包将使x86 [20 vs 8]的存储需求增加一倍以上,在x64 [32 vs 8]中的存储需求增加四倍)。
如果大多数项目都很简单,但有一些复杂的项目,那么另一种方法是使用一个结构体,其中包含"简单"项目的数据以及用于补充信息的引用类型。例如,如果有一个绘图操作列表,最常见的是"moveto"或"lineto",每个操作只需要一个x
和y
,但有些操作需要更多的信息,可以定义一个struct:
structure DrawListEntry {public int X,Y; public DrawOperation Op;}
对于moveto
和lineto
表项,op
将保存对单例的引用;对于像ShowBitmap
这样的条目,它可以保存对封装任意附加信息的非单例对象的引用。如果90%的绘制条目是"移动的"或"行向的",这种方法将需要12或16字节,而不是24或32]。将大多数条目的存储成本削减一半将是一个巨大的胜利。此外,var it=myList[index]; it.Op.Draw(it.X, it.Y)
的缓存性能(it.Op
在90%的情况下识别两个单例之一)可能比在完全独立的对象实例上调用it.Draw()
要好。
如果struct
不是您唯一的选择,您应该尝试使用继承:
abstract class Fruit {
}
class Apple : Fruit {
}
class Orange : Fruit {
}
List<Fruit> fruits = new List<Fruit>();
fruits.Add(new Apple());
等和