问题描述
我有一段代码,用于检查对象是否属于 Sequence<T>
类型,该代码适用于 Task
类型的对象。
public class Sequence<T> {}
public class Task : Sequence<Task> {}
public class Program
{
public static void Main()
{
var task = new Task();
// These two are equivalent
Console.WriteLine(IsSequence(task));
Console.WriteLine(task is Sequence<Task>);
}
public static bool IsSequence<TEntity>(TEntity entity)
{
return entity is Sequence<TEntity>;
}
}
但是,现在我有一个新要求,这些其他类型 Tool
和 Assembly
也应该匹配,而且我对 C# 中的模式匹配很陌生,所以不确定如何实现它.
public class Sequence<T> {}
public abstract class Item : Sequence<Item> {}
public class Task : Sequence<Task> {}
public class Tool : Item {}
public class Assembly : Item {}
public class Program
{
public static void Main()
{
var ta = new Tool();
var tt = new Assembly();
var task = new Task();
Console.WriteLine(IsSequence(ta));
Console.WriteLine(IsSequence(tt));
Console.WriteLine(IsSequence(task));
// What I am posting here is an oversimplification of the real scenario
// This code for checking if something is a Sequence or not is
// handled by a core class with shared functionality that can't kNow or use the
// proper typed overload required.
//
// So doing this is not an option:
//
// Console.WriteLine(IsSequence<Item>(ta));
// This is how the output should be
Console.WriteLine(ta is Sequence<Item>);
Console.WriteLine(tt is Sequence<Item>);
Console.WriteLine(task is Sequence<Task>);
}
public static bool IsSequence<TEntity>(TEntity entity)
{
// How to rewrite (if possible) this pattern matching so that Task,Tool and Assembly match?
// So basically I want to kNow if either TEntity or some of the base types is Sequence<base>
return entity is Sequence<TEntity>;
}
}
我知道它目前的编写方式不会匹配,因为 Tool
/Assembly
不是 Sequence<Tool>
/Sequence<Assembly>
,所以我需要一种方法重写模式匹配以检查它是否为 Sequence<Item>
。
这是一个带有此示例的 C# Online Fiddle。
解决方法
您编写函数的方式不起作用,因为 Tool
不是 Sequence<Tool>
,而是 Sequence<Item>
。
如果您选择保留函数,无论出于何种原因,有很多方法可以编写它,但我会给您两种方法。
首先,您可以编写它来接收一个 object
参数,然后在里面使用 is Sequence<T>
来确定它是否是一个序列。这样做的问题是每次都需要提供类型参数,这里没有推论。
其次,你可以这样写:
public static bool IsSequence<TEntity>(Sequence<TEntity> entity) => true;
public static bool IsSequence(object obj) => false;
在这种情况下,不需要提供类型参数,只需使用您的对象调用它,它就会返回正确的值。由于它依赖于编译时重载解析,因此在运行时非常高效。此外,任何 C++ 程序员都应该熟悉它!
作为第三种选择,从您的 ISequence
类中提取一个接口 Sequence<T>
,然后简单地使用 is ISequence
进行测试,没有类型参数,因为您似乎并不关心它测试。