public class MyClass<T>
{
public T Value;
}
我想实例化一些项目,例如...
new MyClass<string>
new MyClass<int>
我想把它们添加到一个集合中,但是如何定义这个集合以便它能够保存一系列的通用类型?然后我想在某个时候遍历这个集合,并使用 Value 属性。可行吗?
public class MyClass<T>
{
public T Value;
}
我想实例化一些项目,例如...
new MyClass<string>
new MyClass<int>
我想把它们添加到一个集合中,但是如何定义这个集合以便它能够保存一系列的通用类型?然后我想在某个时候遍历这个集合,并使用 Value 属性。可行吗?
将您的泛型类继承非泛型基类或实现非泛型接口。然后,您可以拥有此类型的集合并在访问集合内容的任何代码中进行转换。
这里是一个示例。
public abstract class MyClass
{
public abstract Type Type { get; }
}
public class MyClass<T> : MyClass
{
public override Type Type
{
get { return typeof(T); }
}
public T Value { get; set; }
}
// VERY basic illustration of how you might construct a collection
// of MyClass<T> objects.
public class MyClassCollection
{
private Dictionary<Type, MyClass> _dictionary;
public MyClassCollection()
{
_dictionary = new Dictionary<Type, MyClass>();
}
public void Put<T>(MyClass<T> item)
{
_dictionary[typeof(T)] = item;
}
public MyClass<T> Get<T>()
{
return _dictionary[typeof(T)] as MyClass<T>;
}
}
dynamic
关键字:http://msdn.microsoft.com/zh-cn/library/dd264736.aspx - TommyMyClass<string>
。 - Steven Jeurisclass Program
{
static void Main(string[] args)
{
var x = new MyClass<string>() { Value = "34" };
var y = new MyClass<int>() { Value = 3 };
var list = new List<IMyClass>();
list.Add(x);
list.Add(y);
foreach (var item in list)
{
Console.WriteLine(item.GetValue);
}
}
private interface IMyClass
{
object GetValue { get; }
}
private class MyClass<T> : IMyClass
{
public T Value;
public object GetValue
{
get
{
return Value;
}
}
}
}
即实现一个空接口,然后创建一个包含实现了该接口的类实例的集合。
更新: 我已经在接口中添加了一个“GetValue”方法,它允许您将MyClass实例的“Value”作为对象访问。如果您想拥有一个包含混合类型的集合,这是目前最好的方法了。
您需要为MyClass定义一个基类,然后您的集合将是一个基类的列表。例如:
void Main()
{
var a = new MyClass<string>();
var b = new MyClass<int>();
var c = new List<MyBase>();
c.Add(a);
c.Add(b);
}
public class MyBase { }
// Define other methods and classes here
public class MyClass<T> : MyBase {
public T Value { get; set;}
}
我的大多数通用类型都有带有“未类型化”的成员的接口:
private interface IMyClass
{
object UntypedValue { get; }
}
private class MyClass<T> : IMyClass
{
T Value { get; set; }
object UntypedValue { get { return Value; } }
}
您也可以通过显式接口实现来实现这一点,但在我看来,使用单独的名称更容易。 (也有一些关于显式接口实现的CA提示)
您希望拥有一个MyClass的集合,其中每个实例的类型参数T的值不同。在.NET中这是不可能的;它缺乏Java通配符(?)的等效物。相反,您需要创建一个非泛型的基类或接口,MyClass可以实现它。例如:
public interface IMyClass {
object Value { get; set; }
}
public class MyClass<T> : IMyClass {
public T Value { get; set; }
object IMyClass.Value {
get { return Value; }
set { Value = (T)value; }
}
}
List<IMyClass> m = new List<IMyClass> { new MyClass<string>(), new MyClass<int> };
CompositeCollection cc = new CompositeCollection();
cc.Add(1);
cc.Add("Item One");
cc.Add(1.0M);
cc.Add(1.0);
cc.Add("Done");
Console.WriteLine ("Every Item");
foreach (var element in cc)
Console.WriteLine ("\t" + element.ToString());
Console.WriteLine (Environment.NewLine + "Just Strings");
foreach (var str in cc.OfType<string>())
Console.WriteLine ("\t" + str);
/* Outputs:
Every Item
1
Item One
1.0
1
Done
Just Strings
Item One
Done
*/
CompositeCollection
相对于List<object>
有什么价值? - Mike Christiansenobject
的拆箱可能是任何东西,而CompositeCollection
是一个类型安全的已知实现,它是一组ICollection
/IList
的事物。它还遵循INotifyCollectionChanged
,而object
当然可能不会。它的已知存在允许控件处理一个集合,这有助于绑定;主要用于WPF。 - ΩmegaManIList
和IEnumerable
,但没有实现IList<T>
或IEnumerable<T>
。它的Add
方法接受一个object
。它的索引器接受并返回object
。源代码显示它由一个ArrayList
支持。CompositeCollection
类型似乎只是一种特殊类型的ArrayList
,具有WPF需要的特殊处理,例如实现INotifyCollectionChanged
和ICollectionViewFactory
。 - Mike ChristiansenMyClass<int>
和MyClass<string>
在运行时是完全不同的类型。它们就像MyIntClass
和MyStringClass
一样,你显然不能在没有装箱的情况下将它们放在同一个列表中。它们不一定继承相同的基类、实现相同的接口或其他任何东西。它们与其他任何两种类型一样不同,你必须对待它们如此(即使你认为你知道得更好)。另一种方法是使用非泛型类,并传递一个处理程序来从内部执行操作。
interface IMyClass
{
void ShowValues(MyHandler handler);
}
// Contains a List<string>.
class MyClassString : IMyClass
{
private List<string> _list = new List<string> { "hello", "world" };
public void ShowValues(MyHandler handler)
{
handler.ShowValues(_list);
}
}
// Contains a List<int>.
class MyClassInt : IMyClass
{
private List<int> _list = new List<int> { 1, 2 };
public void ShowValues(MyHandler handler)
{
handler.ShowValues(_list);
}
}
// Handler that has overloaded methods for all the supported types.
class MyHandler
{
public void ShowValues(IEnumerable<string> list)
{
foreach (var item in list)
{
Console.WriteLine(item);
}
}
public void ShowValues(IEnumerable<int> list)
{
foreach (var item in list)
{
Console.WriteLine(item);
}
}
}
class Program
{
static void Main(string[] args)
{
var myClasses = new IMyClass[]
{
new MyClassString(),
new MyClassInt(),
};
var myHandler = new MyHandler();
foreach (var myClass in myClasses)
{
myClass.ShowValues(myHandler);
}
}
}
IList
无法定义一个可以接受任何泛型类的任何变体的通用集合...即 IList<MyClass>
。泛型类只是为了让开发人员节省编写大量重复代码的捷径,但在编译时,每个泛型类的变体都被转换为具体的类。例如,如果您有MyClass<string>
、MyClass<int>
和MyClass<bool>
,那么编译器将生成3个不同的类。实现您想要的唯一方法是为您的泛型创建一个接口。
public interface IMyGeneric {
Type MyType { get; set;}
}
class MyGeneric<T> : IMyGeneric {
public MyGeneric() {
MyType = typeof(T);
}
public Type MyType {
get; set;
}
}
然后你可以说
IList<IMyGeneric> list = new List<IMyGeneric>();
list.add(new MyGeneric<string>());
list.add(new MyGeneric<int>());