c# - 与基类和泛型类型匹配的 C# 模式
问题描述
我有这段代码可以检查对象的类型是否Sequence<T>
符合 Type 对象的预期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
are not Sequence<Tool>
/不会匹配Sequence<Assembly>
,所以我需要一种方法来重写模式匹配以检查它是否是Sequence<Item>
.
这是带有此示例的C# Online Fiddle 。
解决方案
您编写函数的方式不起作用,因为Tool
不是 a Sequence<Tool>
,而是 a Sequence<Item>
。
如果您选择保留它,无论出于何种原因,有很多很多方法可以编写您的函数,但我会给您两种方法。
首先,您可以编写它来接收一个object
参数,然后使用is Sequence<T>
inside 来确定它是否是一个序列。这样做的问题是您每次都需要提供类型参数,这里没有推论。
其次,你可以这样写:
public static bool IsSequence<TEntity>(Sequence<TEntity> entity) => true;
public static bool IsSequence(object obj) => false;
在这种情况下,不需要提供类型参数,只需使用您的对象调用它,它就会返回正确的值。而且由于它依赖于编译时重载决议,它在运行时非常有效。另外,任何 C++ 程序员都应该熟悉它!
作为第三种选择,ISequence
从您的Sequence<T>
类中提取一个接口,然后简单地is ISequence
使用不带类型参数的方式进行测试,因为您在测试中似乎并不关心它。
推荐阅读
- javascript - CHART.JS 如何将 y 轴上的标签偏移/移动/调整到网格线的中间,而不是在网格线上居中?
- c# - 为什么在运行时肯定会失败的 List.Sort 编译?
- html - 如何调整 CSS 以使关闭按钮看起来在正确的位置?
- c# - 如何从存储为 C# 中的对象的对象 [] 进行转换
- javascript - ReactJS/Javascript:componentDidMount() 和渲染
- linux - 如何根据修改时间对Cent OS 7目录中具有特定扩展名的所有文件进行排序?
- javascript - 异步更新 Zabuto 日历
- python-3.x - 为什么在尝试解码我的 base32 字符串时出现“不正确的填充”错误?
- json - 在 Hyperledger Fabric 中存储 JSON 文档
- c# - 如何查询特定类型然后获取基础文档