簡體   English   中英

強制用戶在C#中使用正確的泛型方法

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM