6

这可能是一个愚蠢的问题,但请帮助回答。目前我有一个带有 2 个通用方法的接口:

ValidationResult Validate<T>(T t);


IList<ValidationResult> ValidateList<T>(IEnumerable<T> entities);

我想要的是如果你想验证一个对象,使用Validate方法;如果你想验证一个对象数组,使用ValidateList方法,思路和界面非常清晰。但似乎用户也可以Validate在没有任何编译器错误的情况下对对象列表使用方法(当然!)。有什么方法可以限制他们使用ValidateList方法吗?太感谢了。

4

4 回答 4

2

您可以通过在函数声明中执行以下操作来将函数限制为特定的对象类型(及其派生类):

ValidationResult Validate<T>(T t) where T : ValidateBase, ValidateBaseOther

编辑:

所以在这种情况下,该函数将只接受ValidateBase其或其派生类或其ValidateBaseOther派生类的对象。如果你愿意,你当然可以只用一个

ValidationResult Validate<T>(T t) where T : ValidateBase
于 2013-05-06T14:45:55.533 回答
-1

由于没有找到更好的选择:检查类型是否传递给了Validateimplements 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;
    }
于 2013-05-06T16:18:02.087 回答
-1

您可以执行以下操作:

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);
于 2013-05-06T19:14:32.037 回答
-1

简而言之,你不能用泛型解决你的问题(防止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
于 2013-05-06T14:47:45.197 回答