[英]Generic type constraint to prohibit certain types?
我想創建一個通用方法:
MvcHtmlString MyMethod<T>(this HtmlHelper html, string title, IEnumerable<T> value)
我的代碼中有很多變量,包括List<T>
, IEnumerable<T>
, xxxCollection
, T[]
等......這個方法也有一個重載,它將采用不可枚舉的值。 是否可以在類型參數約束中禁止特定類(如string
)?
我已經創建了一個像這樣的重載:
MvcHtmlString MyMethod<T>(this HtmlHelper html, string title, object value)
這種重載對於處理單個值很有用,但處理值集合需要稍微不同的實現。 但是, string
實現IEnumerable
所以我的所有字符串變量都將被發送到錯誤的重載,除非我可以告訴編譯器應該排除它們。
不可以。 通用類型參數約束只能強制執行正約束而不是負約束。
運行時類型檢查可能是要走的路:
MvcHtmlString MyMethod<T>(this HtmlHelper html, string title, IEnumerable<T> value)
{
if (typeof(T) == typeof(string))
{
throw new IllegalOperationException(...);
}
}
如果要傳遞給方法的所有類型都從相同的基類繼承,或者實現相同的接口,則可以使用jrummell建議的單個約束來強制繼承。
雖然它更不優雅,但如果你想支持異構類型,另一種方法就是提供足夠的重載來處理你的特定用例:
// supports int, float, DateTime, etc.
MvcHtmlString MyMethod(this HtmlHelper html, string title, IEnumerable<int> value)
MvcHtmlString MyMethod(this HtmlHelper html, string title, IEnumerable<float> value)
MvcHtmlString MyMethod(this HtmlHelper html, string title, IEnumerable<DateTime> value)
// supports implementations of MyInterface
MvcHtmlString MyMethod(this HtmlHelper html, string title, IEnumerable<IMyInterface> value)
在上面的示例中,您將無法調用MyMethod<string>
因為它不滿足任何提供的類型約束。 請注意,您不能使用類型約束,因為它們不是方法簽名的一部分。
假設您只想將此擴展用於模型類型,您可以創建一個Model基類並將T
限制為實現它的類型。
MvcHtmlString MyMethod<T>(this HtmlHelper html, string title, IEnumerable<T> value)
where T : ModelBase
考慮到你打算處理string
意圖,你不能使用約束而你不需要它們。
給定您接受類型object
的現有方法,類型為string
的參數將導致您提出的新重載,因為IEnumerable<char>
是一個比object
更好的匹配。 但是,您不必放棄重載的想法,也不需要求助於運行時檢查。 只需為string
創建一個額外的重載。 通過使編譯器的場景更加容易,可以在object
和IEnumerable<T>
之間執行整個決策。
特定
void Foo(object argument)
{
Console.WriteLine("object");
}
void Foo<T>(IEnumerable<T> argument)
{
Console.WriteLine("enumerable T");
}
void Foo(string argument)
{
Console.WriteLine("string");
}
一個方法調用列表
Foo("hello");
Foo(1);
Foo(new int[] { 1 });
產生輸出
string
object
enumerable T
然后,您可以在單個位置進一步強制將字符串強制轉換為對象重載。
void Foo(string argument)
{
// Console.WriteLine("string");
Foo((object)argument);
}
抱歉不行。
您只能指定以下類型的約束:
where T : struct // T must be a value type
where T : class // T must be a reference type
where T : new() // T must have a parameterless constructor
where T : <base class name> // T must inherit from <base class>
where T : <interface name> // T must implement <interface>
where T : U // T must inherit from U, where U is another
// generic parameter
參考: 類型參數的約束 。
現在,您可以使用其中一些來限制,但不能鎖定類型,僅指定您允許的類型,例如接口實現約束。
您可以使用接口或基類約束來明確說“我允許的類型必須具有以下特征”。 我會說這將是你最好的選擇。
你確定仿制葯是正確的工具嗎?
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.