C#中如何让类的Func属性引用其未知(或不关心)的类型?
解决方案:让类的Func属性支持未知类型
在C#场景中,若希望类的Func类型属性能引用其无需关心的未知类型(比如项目A无需了解Person类型,仅需提供可由使用者自定义的筛选器逻辑),以下是可行的解决方案:
方案一:将类定义为泛型类
把MyListType改为泛型类,由调用方指定具体类型T,项目A无需知晓T的具体实现,仅负责维护筛选器的存储逻辑。
项目A代码
// Project A 无需知道具体T类型 public class MyListType<T> { public MyListType(string listName) { ListName = listName; } public string ListName { get; set; } public Func<List<T>, List<T>> Filter { get; private set; } public MyListType<T> WithFilter(Func<List<T>, List<T>> filter) { Filter = filter; return this; } }
项目B代码
public class Person { public Person(string name) { Name = name; } public string Name { get; set; } } public class ClassB1 { public void TestFilter() { var beginsWithA = new MyListType<Person>("Begins with 'A'") .WithFilter(persons => persons.Where(p => p.Name.StartsWith("A")).ToList()); var people = new List<Person> { new Person("Alan"), new Person("Alison"), new Person("Blinky"), new Person("Beatrice"), new Person("Xavier"), new Person("Zebedee") }; var aPeople = beginsWithA.Filter(people); } }
方案二:非泛型接口 + 泛型实现
若需隐藏泛型细节,可定义非泛型接口作为抽象层,内部用泛型类实现具体逻辑。项目A仅暴露非泛型接口,同时保留类型安全。
项目A代码
// 非泛型接口,项目A仅需维护此抽象层 public interface IListFilter { string ListName { get; } object ExecuteFilter(object list); } // 泛型实现类,项目A内部维护 public class ListFilter<T> : IListFilter { public ListFilter(string listName) { ListName = listName; } public string ListName { get; set; } private Func<List<T>, List<T>> _filter; public ListFilter<T> WithFilter(Func<List<T>, List<T>> filter) { _filter = filter; return this; } public object ExecuteFilter(object list) { if (list is List<T> typedList && _filter != null) { return _filter(typedList); } throw new ArgumentException("传入的列表类型不匹配"); } } // 提供入口方法,隐藏泛型细节 public static class ListFilterFactory { public static ListFilter<T> Create<T>(string listName) { return new ListFilter<T>(listName); } }
项目B代码
public class ClassB1 { public void TestFilter() { var beginsWithA = ListFilterFactory.Create<Person>("Begins with 'A'") .WithFilter(persons => persons.Where(p => p.Name.StartsWith("A")).ToList()); var people = new List<Person> { new Person("Alan"), new Person("Alison"), new Person("Blinky"), new Person("Beatrice"), new Person("Xavier"), new Person("Zebedee") }; // 执行后转换回目标类型 var aPeople = (List<Person>)beginsWithA.ExecuteFilter(people); } }
方案三:使用动态类型(不推荐)
若可接受放弃编译时类型检查,可使用dynamic存储筛选器。此方式虽无需关心类型,但会丢失类型安全,增加运行时错误风险。
项目A代码
public class MyListType { public MyListType(string listName) { ListName = listName; } public string ListName { get; set; } public dynamic Filter { get; private set; } public MyListType WithFilter(dynamic filter) { Filter = filter; return this; } }
项目B代码
public class ClassB1 { public void TestFilter() { var beginsWithA = new MyListType("Begins with 'A'") .WithFilter((Func<List<Person>, List<Person>>)(persons => persons.Where(p => p.Name.StartsWith("A")).ToList())); var people = new List<Person> { new Person("Alan"), new Person("Alison"), new Person("Blinky"), new Person("Beatrice"), new Person("Xavier"), new Person("Zebedee") }; var aPeople = beginsWithA.Filter(people); } }
总结
优先选择方案一(泛型类),它既保证编译时类型安全,又让项目A无需关心具体类型;方案二适合需要隐藏泛型细节的场景;方案三仅作临时替代,不推荐用于正式业务逻辑。
内容的提问来源于stack exchange,提问作者komodosp
相关产品推荐
相关产品推荐

