的字典簽名是這樣的:詞典新對象TValue
Dictionary<TKey, TValue>
是否有可能,不知何故,實例化一個新的對象爲TValue
?
我知道我可以從那裏調用一個方法或new
關鍵字,但是我不能在那裏有參數,我希望實例化需要參數的對象。
的字典簽名是這樣的:詞典新對象TValue
Dictionary<TKey, TValue>
是否有可能,不知何故,實例化一個新的對象爲TValue
?
我知道我可以從那裏調用一個方法或new
關鍵字,但是我不能在那裏有參數,我希望實例化需要參數的對象。
既然沒有限制,即TValue
是一個類或有一個構造函數,有「創造」的情況下沒有安全的方式(它可能是TValue
是不具有公共構造類型!)
一一種選擇是使用default
:
var value = default(TValue);
將返回null
對於引用類型,0
數值類型,或初始化爲它的每個成員的struct的默認。
您也可以繼承Dictionary
並添加限制條件爲TValue
有一個默認的構造函數:在一個擴展方法
public class MyDict<TKey,TValue> : Dictionary<TKey, TValue> where TValue : new()
{
public void Add(TKey key)
{
this.Add(key, new TValue());
}
}
或添加限制:
public static class Ext
{
public static void Add<TKey, TValue>(this Dictionary<TKey, TValue> d, TKey key) where TValue : new()
{
d.Add(key, new TValue());
}
}
我同意在具有其類型的參數沒有限制字典貴點,但'TValue'可能取決於使用它(因爲你沒有實例化無法解決的類型參數的字典可)範圍內有限制。如果您在具有與(例如)'類,新的()'的限制,同一類型的'TValue'參數時,那麼你可以做一個'新TValue()的通用參數的函數使用'。但是就原始問題而言,沒有類型參數的限制,暗示某個具有已定義參數的構造函數。 –
@SimonBelanger同意 - 請參閱我的編輯。 –
既然你有沒有澄清了上下文,我想象了一個帶有內部Dictionary<TKey, TValue>
存儲空間的工作方法以及一個工作方法,其中包含任意數量的參數:
public class Beings<TValue>
{
private readonly Dictionary<long, TValue> dictionary;
private readonly Func<object[], TValue> giveBirth;
public Beings(Func<object[], TValue> giveBirth)
{
this.dictionary = new Dictionary<long, TValue>();
this.giveBirth = giveBirth;
}
public TValue Create(params object[] args)
{
var newBeing = this.giveBirth(args);
this.dictionary[this.dictionary.Count] = newBeing;
return newBeing;
}
}
請注意,它的構造函數需要一個Func<object[], TValue>
委託 - TValue中的任何對象。
接下來想象兩個衆生的例子:人類和克隆人。人類通常有媽媽和爸爸,克隆人只有原始的人類。因此,我們有類,如:
[DebuggerDisplay("{Name}")]
public class Human
{
public Human(string name, Human mom, Human dad)
{
this.Name = name;
this.Mom = mom;
this.Dad = dad;
}
public string Name { get; private set; }
public Human Mom { get; private set; }
public Human Dad { get; private set; }
}
public class HumanClone : Human
{
public HumanClone(Human original)
: base(original.Name + "_Clone", null, null)
{
this.Original = original;
}
public Human Original { get; private set; }
}
現在,我們通過Beings<Human>
和Beings<HumanClone>
隔離我們的生活的物種,建立工廠代表們Func<object[], TValue>
簽名:
Func<object[], Human> humanGiveBirth = humanBirthArgs =>
new Human(name: (string)humanBirthArgs[0], mom: (Human)humanBirthArgs[1], dad: (Human)humanBirthArgs[2]);
var humans = new Beings<Human>(humanGiveBirth);
和
Func<object[], HumanClone> humanCloneGiveBirth = humanCloneBirthArgs =>
new HumanClone(original: (Human)humanCloneBirthArgs[0]);
var humanClones = new Beings<HumanClone>(humanCloneGiveBirth);
而對於測試我們的宇宙我們創造了一些物種:
var human1 = humans.Create("Adam", null, null);
var human2 = humans.Create("Eva", null, null);
var human3 = humans.Create("Kain", human2, human1);
var human4 = humans.Create("Avel", human2, human1);
var humanClone1 = humanClones.Create(human1);
var humanClone2 = humanClones.Create(human2);
缺點是您沒有構造函數參數的智能感知,您還必須在工廠代理定義中明確地鍵入轉換每個對象arg。 可能是你可以美化一些事情Delegate.CreateDelegate
和反射魔法......
UPDATE:
但我認爲它的越多,人工代碼看起來...我用TValue Create(params object[] args)
,但我還不如引進TValue Create(Func<TValue> giveBirth)
和使用它像
var human = humans.Create(() => new Human("Elvis", elvisMom, elvisDad));
,創造方法的所有目的是隻注入則委託調用它喜歡的(一些鎖內,例如) - 就像是在ConcurrentDictionary.GetOrAdd Method
做在什麼情況你有做一本字典,你不知道值類型? –