[英]Forcing user to use the right generic method in C#
這可能是一個愚蠢的問題,但請幫助回答。 目前我有一個帶有2種通用方法的接口:
ValidationResult Validate<T>(T t);
IList<ValidationResult> ValidateList<T>(IEnumerable<T> entities);
我想要的是如果你想驗證一個對象,使用Validate
方法; 如果你想驗證一個對象數組,使用ValidateList
方法,非常清楚和界面。 但似乎用戶也可以使用Validate
方法獲取對象列表而不會出現任何編譯錯誤(當然!)。 有沒有辦法將它們限制為ValidateList
方法? 非常感謝。
您可以通過在函數聲明中執行以下操作,將函數限制為特定對象類型(及其派生類):
ValidationResult Validate<T>(T t) where T : ValidateBase, ValidateBaseOther
編輯:
所以在這種情況下,該函數只接受ValidateBase
或其衍生物,或ValidateBaseOther
或其衍生物的對象。 如果你願意,你當然可以使用一個
ValidationResult Validate<T>(T t) where T : ValidateBase
簡而言之,您無法使用泛型來解決問題(防止將IEnumerable<>
傳遞給泛型方法)。 這是因為你不能有負的通用約束(即除了someClass
之外的所有東西)。 存在泛型約束的唯一原因是允許編譯器知道泛型類型上期望的簽名。 它不是為開發人員提供設計時提示。
除了任何未指定的外部要求,您可以在接口處定義泛型類型,而不是方法。 這並不能確保T
不能實現IEnumerable<>
; 但是,它確實確保ValidateList
必須接受傳遞給Validate
的任何內容的列表。 這意味着T
可以是一個數組,但這會強制ValidateList
接受一個數組數組。
如果在方法級別保留泛型類型,即使它們都具有名為T
的泛型類型,這些類型實際上也沒有任何關系。
接口定義的通用類型。
public interface ISomeInterface<T>
{
ValidationResult Validate(T t);
IList<ValidationResult> ValidateList(IEnumerable<T> entities);
}
這將實現如下:
public class SomeClass<T> : ISomeInterface<T>
{
ValidationResult Validate(T t)
{
// Do something ...
}
IList<ValidationResult> ValidateList(IEnumerable<T> entities)
{
// Do something ...
}
}
像這樣使用:
var myInstance = new SomeClass<int>();
int obj = 5;
int arr = new [] {1,2,3};
myInstance.Validate(obj);
myInstance.ValidateList(arr);
myInstance.Validate(arr); // should throw compiler error
由於找不到更好的選項:檢查傳遞給Validate
的類型是否實現IEnumerable<>
。 如果是這樣,可能會提出例外......
所以,在這里:
ValidationResult Validate(T t)
{
Type OutResultNotUsed;
if (typeof(T).IsOrInherits(typeof(IEnumerable<>), out OutResultNotUsed))
throw new Exeption("glkjglkjsdg");
}
用於檢查某些類型是否為或繼承泛型定義的擴展方法。
public static bool IsOrInheritsGenericDefinition(this Type ThisType, Type GenericDefinition, out Type DefinitionWithTypedParameters)
{
DefinitionWithTypedParameters = ThisType;
while (DefinitionWithTypedParameters != null)
{
if (DefinitionWithTypedParameters.IsGenericType)
{
if (DefinitionWithTypedParameters.GetGenericTypeDefinition() == GenericDefinition)
return true;
}
DefinitionWithTypedParameters = DefinitionWithTypedParameters.BaseType;
}
return false;
}
您可以執行以下操作:
public class MultipleValidationResults : ValidationResult, IList<ValidationResult>
{
// stuff...
}
public ValidationResult Validate<T>(T t)
{
if (t is IEnumerable)
// use reflection to call return ValidateList<Y>(t)
// (T is IEnumerable<Y>)
// other stuff
}
MultipleValidationResults ValidateList<T>(IEnumerable<T> entities);
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.