【问题标题】:C# - using List<T>.Find() with custom objectsC# - 将 List<T>.Find() 与自定义对象一起使用
【发布时间】:2011-05-28 14:21:08
【问题描述】:

我正在尝试将List&lt;T&gt; 与我的自定义类一起使用,并且能够使用列表中的Contains()Find() 等方法。我以为我只需要重载运算符 == 但显然,这样做的一种方法是使用带有 Find() 的委托方法...

注意:现在,我重载了Equals() 方法以使Contains() 方法工作,但我仍然无法让Find() 函数工作。

让两者发挥作用的最佳方式是什么?

我在 linux 上使用最新的 C# /.NET 框架版本和单声道。

编辑:这是我的代码

using System;
namespace GuerreDesClans
{
public class Reponse : IEquatable<Reponse>
{
    public Reponse ()
    {
        m_statement = string.Empty;
        m_pointage = 0;
    }

    public Reponse (string statement, int pointage)
    {
        m_pointage = pointage;
        m_statement = statement;
    }


    /*
     * attributs privés
     */

    private string m_statement;
    private int m_pointage;


    /*
     * properties
     */

    public string Statement {
        get { return m_statement; }
        set { m_statement = value; }
    }

    public int Pointage {
        get { return m_pointage; }
        set { m_pointage = value; }
    }

    /*
     * Equatable
     */

    public bool Equals (Reponse other)
    {
        if (this.m_statement == other.m_statement)
            return true;
        else
            return false;
    }
}

}

以及我想如何使用 find() 函数搜索我的响应对象...

list.find("statement1"); // would return a Reponse object

【问题讨论】:

    标签: c# list generics delegates find


    【解决方案1】:

    您可以将 find 与 Predicate 一起使用,如下所示:

    list.Find(x => x.Id == IdToFind);
    

    这将返回列表中满足谓词定义的条件的第一个对象(即在我的示例中,我正在寻找具有 ID 的对象)。

    【讨论】:

    • 这种技术叫什么?
    • @Pacane:来自 msdn - 所有 lambda 表达式都使用 lambda 运算符 =>,读作“goes to”
    【解决方案2】:

    Find() 将查找与您作为参数传递的谓词匹配的元素,因此它与 Equals() 或 == 运算符无关。

    var element = myList.Find(e => [some condition on e]);
    

    在这种情况下,我使用了lambda expression 作为谓词。您可能想阅读此内容。对于 Find(),您的表达式应该接受一个元素并返回一个布尔值。

    在你的情况下,那将是:

    var reponse = list.Find(r => r.Statement == "statement1")
    

    为了回答 cmets 中的问题,这是 .NET 2.0 中的等价物,在引入 lambda 表达式之前:

    var response = list.Find(delegate (Response r) {
        return r.Statement == "statement1";
    });
    

    【讨论】:

    • 你能提供一个 .NET 2.0 的例子吗?我在 Unity3D 中,它被困在 .net 2.0 土地中
    • 是否可以认为返回的元素将是一个引用,并且对它的任何修改都将反映在列表中包含的同一元素上?
    • @HugoAllexisCardona 如果元素的类型是引用类型,那么是的。如果是值类型,则不是。见msdn.microsoft.com/en-us/library/t63sy5hs.aspx
    • 找不到元素怎么处理?
    • @OlivierPons 如果列表包含引用类型,如果未找到该元素,Find 将返回 null。如果列表包含值类型,如果未找到该元素,它将返回该类型的默认值。在这种情况下,没有办法知道是否找到了元素,除非默认值不能匹配谓词。
    【解决方案3】:

    以前的答案没有说明您已经重载了等号运算符并使用它来测试寻找的元素的事实。在这种情况下,您的代码将如下所示:

    list.Find(x => x == objectToFind);
    

    或者,如果你不喜欢 lambda 语法,并且已经重写了 object.Equals(object) 或者已经实现了 IEquatable,你可以这样做:

    list.Find(objectToFind.Equals);
    

    【讨论】:

    • 这些语句都是多余的,因为我们已经引用了 objectToFind。 Find() 的目的是定位我们没有引用的对象。使用 list.Contains(objectToFind) 更容易、更符合逻辑且更易读。
    • @Greg Sansom:当然。但是OP特别说他有Contains方法工作,但也想使用Find。由于他重写了 Equals 以比较 m_statement 并忽略 m_pointage 的值,因此 Find 方法不一定会返回传递给它的相同实例。 Equals 覆盖的行为可能有问题,但鉴于这种行为,list.Find(obj.Equals) 并不是多余的。
    【解决方案4】:

    http://msdn.microsoft.com/en-us/library/x0b5b5bc.aspx

            // Find a book by its ID.
            Book result = Books.Find(
            delegate(Book bk)
            {
                return bk.ID == IDtoFind;
            }
            );
            if (result != null)
            {
                DisplayResult(result, "Find by ID: " + IDtoFind);   
            }
            else
            {
                Console.WriteLine("\nNot found: {0}", IDtoFind);
            }
    

    【讨论】:

      【解决方案5】:

      这很简单,只需使用 list.Find(x =&gt; x.name == "stringNameOfObjectToFind");

      【讨论】:

        猜你喜欢
        • 2015-11-25
        • 2011-10-19
        • 2010-10-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-03-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多