是否有任何方法創建擴展方法,其參數的唯一約束具有特定名稱的屬性。 例如: -僅限於包含特定屬性的對象的擴展方法
public static bool IsMixed<T>(this T obj) where T:?
{
return obj.IsThis && obj.IsThat;
}
我試圖宣佈obj
動態,但它是不允許的。
是否有任何方法創建擴展方法,其參數的唯一約束具有特定名稱的屬性。 例如: -僅限於包含特定屬性的對象的擴展方法
public static bool IsMixed<T>(this T obj) where T:?
{
return obj.IsThis && obj.IsThat;
}
我試圖宣佈obj
動態,但它是不允許的。
此功能通常被稱爲「鴨子打字」。 (因爲當你調用foo.Quack()時,你所關心的就是它像鴨子一樣嘎嘎叫。)非動態鴨子打字不是C#的特色,對不起!
如果你真的有關於參數沒有類型的信息,您可以使用C#動態4:
public static bool IsAllThat(this object x)
{
dynamic d = x;
return d.IsThis || d.IsThat;
}
但它會更好地想出一些接口或描述一些這樣的事情類型在編譯時。
你必須得到T來實現一個接口,然後在約束中使用它。
T是未知的,除了它是一個類。它可能甚至是一個匿名類型。我不需要它來實現一個特定的接口,我需要它包含兩個布爾專門命名的屬性。 正在定義一個接口/基類,並讓每個對象實現它是實現我的目標的唯一方法,您熟悉? – user759141 2011-05-24 13:23:46
@user:如果*需要*'T'來包含兩個專門命名的屬性,那麼您需要'T'來實現一個接口。從概念上講,即使你不想在代碼中做到這一點,這就是你正在做的。 – 2011-05-24 13:53:23
幾乎做到這一點的唯一方法是有一個接口爲你特林操作的類的基礎:
interface iMyInterface
{
}
public static bool IsMixed<T>(this T obj) where T: iMyInterface
{
return obj.IsThis && obj.IsThat;
}
我不明白你的代碼。這裏的通用方法有什麼好處?爲什麼不簡單地擴展IMyInterface,而不是擴展所有類型?你是否打算IMyInterface具有屬性IsThis和IsThat?他們爲什麼不在界面聲明中? – 2011-05-24 15:29:48
@Eric Lippert,是的,我有點匆忙,因爲我覺得這很瑣碎,我離開時沒有添加屬性到界面。 – 2011-05-24 15:48:30
雖然你不能做你要找與泛型約束是什麼,您可以使用反射來檢查運行時的類型,以確定它是否具有這些屬性並動態獲取它們的值。
免責聲明:我正在做這件事情,我可能會略微執行。
public static bool IsMixed(this object obj)
{
Type type = obj.GetType();
PropertyInfo isThisProperty = type.GetProperty("IsThis", typeof(bool));
PropertyInfo isThatProperty = type.GetProperty("IsThat", typeof(bool));
if (isThisProperty != null && isThatProperty != null)
{
bool isThis = isThisProperty.GetValue(this, null);
bool isThat = isThatProperty.GetValue(this, null);
return isThis && isThat;
}
else
{
throw new ArgumentException(
"Object must have properties IsThis and IsThat.",
"obj"
);
}
}
'public static bool IsMixed(this obj){var d =(dynamic)obj; return d.IsThis && d.IsThat; }'而不是,讓運行時間擔心反射,性能等。 – LukeH 2011-05-24 13:37:37
正是我在找的東西。如果沒有適當的通用類型約束條件,這是最好的解決方案 – user759141 2011-05-24 13:40:43
@Aashash:我建議你嘗試一些比較基準測試,而不是僅僅根據代碼來判斷性能。可能確實,使用簡單反射比使用「動態」會更快,但如果經常調用此代碼 - 對於實用程序/擴展方法的合理假設 - 那麼「動態」將比普通代碼快得多反射。 – LukeH 2011-05-24 14:07:15
所以只需確認一下,如果屬性不存在,您將得到一個運行時錯誤,因此您將不得不用try/catch包裝。 – ColWhi 2011-05-24 17:37:07
@Sasquiha:正確;動態代碼假定您正在動態執行的代碼是*正確的*。如果這個假設被違反,那麼拋出異常。 – 2011-05-24 18:07:42