C# 如何强制泛型参数为类型
本文关键字:类型 参数 泛型 何强制 | 更新日期: 2023-09-27 18:36:22
我有通用方法。 我希望泛型方法限制一种类型。 问题是不允许派生类型 - 我不想要这个。 示例代码:
public static T Generate<T>(T input)
where T : Operation // ALLOWS BinaryOperation - NOT WANT THIS
{
//...
}
如何按照我的要求去做?
问题是不允许派生类型
如果不在运行时检查它,就无法强制实施此约束。 这样做将违反 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)
{ // ...
如果
方法不是结构或密封类,则不可能强制方法仅接受一种特定类型,例如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
。
溶液
除了上面提到的其他解决方案(结构,密封)之外,只有一个解决方案:运行时检查。您可以为此编写一个小的帮助程序方法。
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);