2

我有通用方法。我想要通用方法来限制一种类型。问题是不允许派生类型 - 我不想要这个。示例代码:

public static T Generate<T>(T input)
    where T : Operation // ALLOWS BinaryOperation - NOT WANT THIS
{
    //...
}

怎么做我要求的?

4

2 回答 2

10

问题是不允许派生类型

如果不在运行时检查它,就无法强制执行此约束。这样做将违反Liskov 替换原则,该原则规定任何类型都应允许您无限制地传入派生类型。

如果您必须强制执行此操作,则它仅适用于运行时检查,例如:

public static T Generate<T>(T input)
    where T : Operation // ALLOWS BinaryOperation - NOT WANT THIS
{
    // Checks to see if it is "Operation" (and not derived type)
    if (input.GetType() != typeof(Operation))
    {
        // Handle bad case here...
    }

    // Alternatively, if you only want to not allow "BinaryOperation", you can do:
    if (input is BinaryOperation)
    {
        // Handle "bad" case of a BinaryOperation passed in here...
    }
}

请注意,在这种情况下,真的没有理由让它通用,因为相同的代码可以作为:

public static Operation Generate(Operation input)
{ // ...
于 2012-06-04T17:37:36.940 回答
0

不可能强制方法只接受一种特定类型,例如Operation该类型不是结构或密封类。

让我在一个例子中展示一下为什么这无论如何都行不通:

public void Generate<T>(Operation op) 
    // We assume that there is the keyword "force" to allow only Operation classes
    // to be passed
    where T : force Operation
{ ... }

public void DoSomething()
{
    Generate(new BitOperation()); // Will not build
    // "GetOperation" retrieves a Operation class, but at this point you dont
    // know if its "Operation" or not
    Operation op = GetOperation();
    Generate(op); // Will pass
}

public Operation GetOperation() { return new BitOperation(); }

如您所见,BitOperation即使有限制,也很容易通过 a。

解决方案

除了上面提到的其他解决方案(结构,密封)之外,只有一个解决方案:运行时检查。 您可以为此编写一个小辅助方法。

public class RuntimeHelper
{
    public static void CheckType<T>(this Object @this)
    {
        if (typeof(T) != @this.GetType())
            throw new ....;
    }
}

用法

public void Generate(Operation op)
{
    op.CheckType<Operation>(); // Throws an error when BitOperation is passed
}

小笔记

如果您想加快帮助程序的速度,您可以使用RuntimeHelper<T>具有 T 类型的静态只读类型变量的泛型类。

当你这样做时,你不能再使用扩展方法,所以调用看起来像这样:

RuntimeHelper<Operation>.CheckType(op);
于 2012-06-04T18:39:36.530 回答