![](/img/trans.png)
[英]How to call a method with a generic constraint using a type parameter without the constraint?
[英]Parameter constraints - call method to check type in constraint?
我有一個帶有通用參數的方法:
internal void DoSomething<T>(T workWithThis)
{
}
我現在想限制此方法,使其僅接受繼承我要指定的幾個接口之一的參數。 但是我還沒有找到解決方法。 我想要的是這樣的:
internal void DoSomething<T>(T workWithThis) where T : ISomething | ISomethingElse
{
}
顯然,這是行不通的,因此我嘗試使用靜態方法來檢查T的類型:
public static bool CheckType(Type t)
{
return */check here*/
}
internal void DoSomething<T>(T workWithThis) where T : CheckType(typeof(T))
{
}
顯然,這也不起作用。 問題是為什么? 根據我的理解,為什么編譯器會阻止我執行此操作,所以沒有理由不執行它
根據我的理解,為什么編譯器會阻止我執行此操作,所以沒有理由不執行它
編譯器阻止您執行此操作,因為您正在嘗試執行C#不支持的語言。 您嘗試使用的語法不符合C#規范第10.1.5節中的規定。
C#作為一種語言根本不支持您所需的方案。
現在, 為什么該語言不允許這種靈活性-歸結為以下常規平衡行為:
哦,這當然不僅僅是C#-CLR也必須支持這種限制,並且至少會鼓勵其他CLR語言也理解它。
我建議您通過兩種單獨的方法來解決此問題。 請注意,它們不能只是泛型方法的重載,因為重載不能僅因泛型類型約束而有所不同。 如果您不介意為實現接口的值類型裝箱,則可以使用以下方法進行重載:
internal void DoSomething(ISomething something)
{
}
internal void DoSomething(ISomethingElse somethingElse)
{
}
...盡管盡管如此,如果您傳入一個表達式是同時實現兩個接口的類型的值,則最終將導致過載歧義。
或者,只需給這兩種方法取不同的名稱。
編譯器必須在編譯時驗證所有約束,並且不能調用方法來進行驗證。
您可以在where
約束中指定的唯一內容是:
new()
-需要無參數構造函數 class
-必須是引用類型 struct
必須為值類型 SomeBaseClass
ISomeInterface
T : U
必須是,可以繼承或實現其他通用參數之一 有關更多信息,請參見C#編程指南-類型參數的約束 。
至於為什么,您永遠不必回答“我認為沒有任何理由使它起作用”。 您必須從相反的方向開始,“為什么要這樣做”,然后提出足夠合理可行的方案和要求,以使其值得實施。 參見Eric Gunnerson的減100分 。
要在代碼中解決此問題,您應該從一個公共接口派生兩個接口,並在其上添加約束。
如果兩個接口沒有共同點,那么我首先質疑實際上添加約束的好處。
例如,如果您的代碼要在與泛型類型/方法一起使用的對象上調用方法,那么顯然兩個接口必須對該方法的含義具有相同的概念,而唯一的方法是在通用基本接口中定義的方法。 兩個接口碰巧聲明了具有相同簽名的相同方法或屬性,但並沒有使其成為相同的方法。
話雖如此,您確定這里甚至需要泛型嗎?
只聲明兩個方法,每個方法采用一個這樣的接口怎么樣?
internal void DoSomething(ISomething workWithThis)
internal void DoSomething(ISomethingElse workWithThis)
編譯器使用通用約束來確定通用方法中T上可用的操作-因此允許or表達式將不是類型安全的。 例如,您有兩個接口IFirst
和ISecond
:
public interface IFirst
{
void First();
}
public interface ISecond
{
void Second();
}
internal void DoSomething<T>(T workWithThis) where T : IFirst or ISecond
{
//How to call this method if the type is ISecond
workWithThis.First();
//How to call this method if the type is IFirst
workWithThis.Second();
}
您可以定義一個包含所有接口的空接口。
請記住,在C#
接口中可以具有多個繼承。
例如:
public interface IHolder : ISomething, ISomethingElse
{
}
對於通用
internal void DoSomething<T>(T workWithThis) where T : IHolder
{
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.