,如果我有一個泛型類:集合泛型類型
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>;
}
}
返回類型是一個有趣的變化。 – 2010-07-09 18:55:56
你的解決方案絕對是優雅的。保持類型的內部字典確實可以實現更簡單的訪問方法。 – 2010-07-12 14:57:23
此外,您現在可以使用'dynamic'關鍵字:http://msdn.microsoft.com/en-us/library/dd264736.aspx – Tommy 2014-02-19 19:31:21
我能想到的唯一的辦法,把我的頭頂部如下(在一個控制檯應用程序進行測試包裹起來):
class 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;
}
}
}
}
即有無MyClass的實現一個空的接口,然後創建集合作爲持有實現該接口的類的實例的集合。
更新: 我添加了一個「的GetValue」的方法,可以讓你訪問的MyClass的實例的「價值」爲對象的接口。如果你想擁有一個擁有混合類型的集合,那麼它就像它將要得到的一樣好,afaik。
良好的調用 - 這是我使用基類的等價答案:) – 2010-07-09 18:21:12
但是,如何訪問value屬性? – 2010-07-09 18:23:56
問題是他想要一個Value屬性,該屬性最終具有正確的類型,但無法確定。 – CodingWithSpike 2010-07-09 18:25:21
你會想爲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;}
}
你想擁有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> };
@ commongenius,你確認它不會編譯?它在VS2k8中爲我編譯得很好 – Rob 2010-07-09 18:33:42
當我發佈我的評論時,原來的帖子已經改變了。我相應地改變了我的評論。 – 2010-07-09 18:38:48
我有我的大部分泛型類型與「無類型」的成員接口:
private interface IMyClass
{
object UntypedValue { get; }
}
private class MyClass<T> : IMyClass
{
T Value { get; set; }
object UntypedValue { get { return Value; } }
}
您還可以通過使用顯式接口實現的做到這一點,但在我看來,通過使用單獨的名稱更容易。(上有顯式接口實現一些CA提示以及)
+1提供鍵入和未鍵入的值。 – 2010-07-09 18:55:05
的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>());
我覺得這裏的問題是,泛型類真的不是同一類型的。它們只是在編譯時創建全新類型的模板(如果我理解正確的話)。因此,根據運行時間,MyClass<int>
和MyClass<string>
是完全不同的類型。他們可能是MyIntClass
和MyStringClass
,你顯然不能在同一個列表中沒有先裝箱。他們不(必然)繼承相同的基類,實現相同的接口或其他任何東西。它們與其他任何兩種類型都不同,你必須像對待它們一樣對待它們(即使你認爲你知道的更好)。
當然,你可以讓他們實現一個接口,繼承一個基礎對象,或任何其他已經給出的選項。看看commongenius' answer是一個很好的方法來做到這一點。
由於淨3出現了CompositeCollection類,它允許多個獨特的項目,甚至藏品被包含在內。它由WPF開發人員用來在Xaml中存儲和顯示不同的項目。但這並不意味着它不能用於非WPF的情況。
這裏就是我的琴絃不同的東西存儲小數和提取,並列舉了所有項目,那麼一個特定類型的項目的例子:
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
*/
你怎麼宣佈你的班?你如何定義後備集合? – Oded 2010-07-09 18:16:45
這只是一個「假設」,或者你正在試圖用作解決方案的一部分?我問,因爲給了更多的上下文,我們可能會建議一個更好的答案.. :) – Rob 2010-07-09 18:37:16
幾乎相同的問題後來轉貼(我投票結束,但可能沒有它,因爲它是如此之久):http: //stackoverflow.com/q/3777057/590790 – 2015-12-25 15:20:31