[英]C# how to force generic argument to be type
我有通用的方法。 我想要通用方法來限制一種類型。 問題是派生類型不被允許 - 我不想要這個。 示例代碼:
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);
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.