gpt4 book ai didi

c# - 如何使用C#中的委托(delegate)来实现使用接口(interface)和实现类的类似设计(从Java)

转载 作者:太空狗 更新时间:2023-10-29 22:30:12 26 4
gpt4 key购买 nike

我在Java(7)应用程序中有以下设计:

有一种方法可以传递某种类型的对象和称为“谓词”的对象的集合,该对象用于过滤给定的集合。

谓词是具有一个称为test的方法的接口(interface)-它接受一个对象并返回一个 bool 值。

在这种情况下:

  • 任何人都可以通过创建实现Predicate
  • 的类来编写自己的Predicate接口(interface)实现。
  • 通过在调用过滤方法
  • 的过程中创建匿名实现,任何人都可以编写其自己的Predicate接口(interface)实现。
  • 有一组预定义的实现谓词的类,它涵盖了许多标准情况,因此在大多数情况下,无需编写新的实现。
  • 还有一个实用程序类,提供了一些静态方法,例如和,或allOf,anyOf,可将作为输入提供的谓词组合到新谓词中(内部将返回新谓词的匿名实现)。

    现在,我想在C#(4.0)应用程序中进行类似的设计。我可以看到两种实现方式-通过模仿Java设计,或通过将谓词更改为委托(delegate):

    我可以尝试模仿Java设计,但是:
  • 据我所知,没有像C#中的接口(interface)的匿名实现那样的东西(因此在调用filter方法时无需创建新的谓词,而我的util类不必基于匿名实现,但是第二个不是真正的问题)
  • 我觉得这不是C#的方式来做这些事情

  • 我可以尝试使用委托(delegate)来实现类似的设计。我的过滤器方法将收集对象和谓词委托(delegate)。在这种情况下:
  • 我不知道当人们能够编写某种将“实现”委托(delegate)的类型时如何实现。我想象一种情况,有人会使用与委托(delegate)的签名相匹配的方法编写类-我对此策略并不满意,因为如果我有实现的接口(interface)-编译器将迫使我具有正确的签名-并且因为我不能“扩展” “或”实现”委托(delegate)-编译器仅在尝试将对此方法的“引用”传递给我的过滤方法时才会告诉我是错误的(当然,这仍然是编译时错误)。
  • 任何人都可以通过传递lambda或指向具有与Predicate委托(delegate)匹配的签名的方法来编写其自己的Predicate接口(interface)实现。因此,这将与Java中的
  • 相同
  • 当我有预定义的谓词集时,我不知道如何实现。从技术的角度来看,我当然知道这很简单-例如,我可以使用与委托(delegate)的签名相匹配的静态方法编写一个类-每个方法将覆盖一个谓词。但是我感觉这种方法有点不一致-因为在一个地方会有预定义的谓词,而用户的谓词将在另一个地方定义(在Java中,预定义和用户定义的谓词都是实现接口(interface)的类)
  • 如果谓词将被委托(delegate)-我也可以编写一些Util类,该类可以通过多种方式组合谓词。这也与Java
  • 中的相同

    我的问题是-在您看来,什么是实现与Java中相同(或尽可能相似)设计的最佳方法,这将被视为正确,干净的C#方法?

    我在Java编程方面有几年的经验,但在C#中则不到一年,因此我了解到,也许我看到的某些问题在C#世界中根本不存在,或者根本不认为是问题。

    编辑:这是我的Java代码如何工作的最简单的示例(我认为...):

    我的“域”对象:
    public class Person {

    private final String firstName;
    private final String secondName;

    public Person(String firstName, String secondName) {
    this.firstName = firstName;
    this.secondName = secondName;
    }

    public String getFirstName() {
    return firstName;
    }

    public String getSecondName() {
    return secondName;
    }
    }

    过滤类:
    public class Filter {
    public Collection<Person> filter(Collection<Person> collection, Predicate predicate) {
    Collection<Person> result = new LinkedList<Person>();
    for(Person person: collection) {
    if(predicate.test(person)) {
    result.add(person);
    }
    }
    return result;
    }
    }

    谓词接口(interface):
    public interface Predicate {
    boolean test(Person person);
    }

    两个简单的预定义实现:
    public class FirstNameStartsWithPredicate implements Predicate {

    private final String startsWith;

    public FirstNameStartsWithPredicate(String startsWith) {
    this.startsWith = startsWith;
    }

    public boolean test(Person person) {
    return person.getFirstName().startsWith(startsWith);
    }
    }

    public class LastNameEndsWithPredicate implements Predicate {

    private final String endsWith;

    public LastNameEndsWithPredicate(String endsWith) {
    this.endsWith = endsWith;
    }

    public boolean test(Person person) {
    return person.getSecondName().endsWith(endsWith);
    }
    }

    实用程序类:
    public final class PredicateUtils {

    public static Predicate and(final Predicate first, final Predicate second) {
    return new Predicate() {
    public boolean test(Person person) {
    return first.test(person) && second.test(person);
    }
    };
    }

    public static Predicate or(final Predicate first, final Predicate second) {
    return new Predicate() {
    public boolean test(Person person) {
    return first.test(person) || second.test(person);
    }
    };
    }

    public static Predicate allwaysTrue() {
    return new Predicate() {
    public boolean test(Person person) {
    return true;
    }
    };
    }
    }

    最后,用法示例:
    Collection<Person> persons = Arrays.asList(
    new Person("John", "Done"),
    new Person("Jane", "Done"),
    new Person("Adam", "Smith")
    );

    Filter filter = new Filter();

    // Predefined predicates
    filter.filter(persons, new FirstNameStartsWithPredicate("J"));
    filter.filter(persons, new LastNameEndsWithPredicate("e"));

    // anonymous implementation
    filter.filter(persons, new Predicate() {
    public boolean test(Person person) {
    return person.getFirstName().equals("Adam") && person.getSecondName().equals("Smith");
    }
    });

    // utility class
    filter.filter(persons, PredicateUtils.allwaysTrue());
    filter.filter(persons, PredicateUtils.and(new FirstNameStartsWithPredicate("J"), new LastNameEndsWithPredicate("e")));
    filter.filter(persons, PredicateUtils.or(new FirstNameStartsWithPredicate("J"), new FirstNameStartsWithPredicate("A")));

    最佳答案

    这在C#中完全可行。假设我们有几个用户,并使用过滤器对其进行过滤,一些过滤器是内置的,有些由用户实现。在这里,我们应该使用Java之类的接口(interface)来代替委托(delegate)。

    public class User
    {
    public string Name { get; set; }
    public int Age { get; set; }
    public string Address { get; set; }
    }

    public interface IPredicate<T>
    {
    bool IsValid(T entity);
    }

    public class UserPredicate : IPredicate<User>
    {
    /* built-in predicates */
    public static UserPredicate Adult = new UserPredicate(u => u.Age >= 18);
    public static UserPredicate NoAddress = new UserPredicate(u => string.IsNullOrEmpty(u.Address));

    public Func<User, bool> Predicate { get; private set; }
    public UserPredicate(Func<User, bool> predicate)
    {
    this.Predicate = predicate;
    }

    bool IPredicate<User>.IsValid(User entity)
    {
    return this.Predicate(entity);
    }
    }

    用户可以轻松地添加新的谓词,如下所示:
    //user's code
    var custom = new UserPredicate(MyCustomUserFilter);

    bool MyCustomUserFilter(User u)
    {
    //user's filter logic
    }

    它与Java不同,因为在C#中,匿名类型无法实现接口(interface)。

    而且,将谓词“组合”成一个新的谓词也很容易。
    var AdultWithNoAddress = new UserPredicate(u => UserPredicate.Adult.Predicate(u) 
    && UserPredicate.NoAddress.Predicate(u));

    编辑为了使谓词组合更加清晰,您可以将组合逻辑放到谓词本身中。
    public interface IPredicate<T>
    {
    bool IsValid(T entity);

    IPredicate<T> And(IPredicate<T> another);

    IPredicate<T> Or(IPredicate<T> another);
    }

    public class UserPredicate : IPredicate<User>
    {
    public static UserPredicate Adult = new UserPredicate(u => u.Age >= 18);
    public static UserPredicate NoAddress = new UserPredicate(u => string.IsNullOrEmpty(u.Address));

    private Func<User, bool> _predicate;
    public UserPredicate(Func<User, bool> predicate)
    {
    _predicate = predicate;
    }

    public bool IsValid(User entity)
    {
    return _predicate(entity);
    }

    public IPredicate<User> And(IPredicate<User> another)
    {
    return new UserPredicate(u => this.IsValid(u) && another.IsValid(u));
    }

    public IPredicate<User> Or(IPredicate<User> another)
    {
    return new UserPredicate(u => this.IsValid(u) || another.IsValid(u));
    }
    }

    //usage
    var AdultWithNoAddress = UserPredicate.Adult.And(UserPredicate.NoAddress);

    关于c# - 如何使用C#中的委托(delegate)来实现使用接口(interface)和实现类的类似设计(从Java),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37250412/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com