這似乎是C#語言設計者沒有想到的。你(和我)正在尋找的是Funcs/Delegates的編譯時「接口」,所以它們基本上可以用在一個集合中。
問你的問題的另一種方式是我怎麼約束別人傳遞一個這樣的數組:
new[] {
new Func<MaxLengthAttribute, string>(a => "maxlength=" + a.Length),
new Func<RequiredAttribute, string>(a => "required")
}
要只通過格式Func<out Attribute, string>
的funcs中?應該是簡單的...不是?
不可以。作爲鏈接的其他答案,out關鍵字不允許輸入參數,如我們在此使用的輸入參數。
如果你必須在你不得不擁有類似Java的醜陋雜技編譯時的約束:
public interface IHasMethod<T>
where T : BaseClass
{
void MethodToCheck<T>(T, object);
}
public class Class1 : IHasMethod<DerivedClass>
{
public object MethodToCheck(DerivedClass d)
{
}
}
這意味着你的測試看起來像:
public void CheckMethod(IHasMethod methodHaver)
{
}
Eugh。同樣,我的數組示例變爲:new IHasMethod[]
如果您更喜歡在運行時只受保護/檢查的更漂亮,更脆弱的代碼,那麼您的替代方案是Delegate
。您的簽名:
public void CheckMethod(Delegate func)
我的數組例如:
new Delegate[] ...
但在這兩種情況下,你處於危險之中是因爲這代表的格式是無界的,在編譯時 - 它現在對你做什麼通常成爲編譯器的問題,在繼續之前檢查正確數量的參數及其類型。如果可以的話,嘗試僅在調試代碼中進行醜陋的檢查,並調用解壓縮並暴露給單元測試的方法,以便儘管編譯安全性已經喪失,但應使用自動化測試安全性替換它。像:
#if DEBUG
foreach(var attrTempl in attributeTemplates)
{
var templParams = attrTempl.Method.GetParameters();
if (templParams.Length != 1)
throw new Exception("Can't have " + templParams.Length + " params in AttributeTemplate Delegate, must be Func<out Attribute, string>");
var type1 = templParams[0].ParameterType;
var type2 = attrTempl.Method.ReturnType;
if (!type1.IsSubclassOf(typeof(System.Attribute)))
throw new Exception("Input parameter type " + type1.Name + " must inherit from System.Attribute");
if (type2 != typeof(string))
throw new Exception("Output parameter type " + type2.Name + " must be string");
}
#endif
對該欄的最後一個幫手:如果你把Delegate
方法,你會轉換代碼看起來像這樣:
Func<A, B> fn
要這樣:
Delegate fn
您可能在某些時候稱爲Func,如:
var b = fn(a);
現在會出現編譯錯誤,因爲編譯器準確地聲明它不知道該委託是否接受任何參數。可愛。你可以踢過去它的運行時間:
var b = (B)fn.DynamicInvoke(a);
Related
我很好奇,爲什麼你有使用泛型一個完全可行的解決方案,但你正在尋找的唯一標準是不同的解決方案它應該需要更少的打字。你的目標是什麼?減少編程團隊的RSI? – 2011-05-10 12:19:49
主要原因是我只對實際方法感興趣。但是,參數和返回數據是方法簽名的一部分,所以我想這是不可能的。 – 2011-05-12 06:23:36
這正是我在我的帖子中所說的:)。我認爲這應該被標記爲答案。 – 2011-05-29 10:49:50