为什么LINQ找不到具有包含特定子字符串的属性的项目?

时间:2018-12-21 07:41:32

标签: c# string linq

我的应用程序从服务器接收消息列表。消息对象具有“文本”属性。从这个列表中,我试图找到第一项,其中“文本”包含特定的子字符串。 例如,响应可能在列表中包含此类元素(已保存顺序):

Text = "mye:service?resp=out&text=some_text&id=854217";
Text = "mye:service?resp=inj&text=some_text&id=854219";
Text = "mye:service?resp=corr&text=some_text&id=854220";
Text = "mye:service?resp=out&text=some_text&id=854223";
Text = "mye:service?resp=inj&text=some_text&id=854227";
Text = "mye:service?resp=corr&text=test&id=854230";

这是我尝试获取正确商品的方式:

Message suitableMessage = messagesList.FirstOrDefault(m => m.Text.Contains("param") || m.Text.Contains("corr"));

它总是返回第一个元素,这个元素:

Text = "mye:service?resp=out&text=some_text&id=854217";

在调试器中查看列表项,我发现有合适的元素。

我在做什么错了?

3 个答案:

答案 0 :(得分:0)

您使用的是.FirstOrDefault()(如果找不到您的案例,则是第一个或null),为什么要争相获得与第一个匹配项不同的东西?

如果要获取所有匹配项的数组(或更准确地说是IEnumerable),请改用.Where()

答案 1 :(得分:0)

如果运行此示例,您将看到LinQ可以正常工作:

    static void Main(string[] args)
    {
        var messagesList = new List<Message>
        {
            new Message {Text = "mye:service?resp=out&text=some_text&id=854217"},
            new Message {Text = "mye:service?resp=inj&text=some_text&id=854219"},
            new Message {Text = "mye:service?resp=corr&text=some_text&id=854220"},
            new Message {Text = "mye:service?resp=out&text=some_text&id=854223"},
            new Message {Text = "mye:service?resp=inj&text=some_text&id=854227"},
            new Message {Text = "mye:service?resp=corr&text=test&id=854230"}
        };

        Message suitableMessage = messagesList.FirstOrDefault(m => m.Text.Contains("param") || m.Text.Contains("corr"));
        //result:
        //suitableMessage == "mye:service?resp=corr&text=some_text&id=854220"

        //verification
        if (suitableMessage.Text.Contains("param"))
        {
            Console.WriteLine("param");
        }

        if (suitableMessage.Text.Contains("corr"))
        {
            Console.WriteLine("corr");
        }

        //verification 2 - you can replace your LinQ with this code and debug
        Message suitableMessage2;
        string reason;
        string text; // just to make sure that value is not changed by some other thread ...
        foreach (var m in messagesList)
        {
            if (m.Text.Contains("param"))
            {
                suitableMessage2 = m;
                text = m.Text;
                reason = "param";
                break;
            }

            if (m.Text.Contains("corr"))
            {
                suitableMessage2 = m;
                text = m.Text;
                reason = "corr";
                break;
            }
        }

        // verification 3 - replace lambda with method if not sure how to add break point, write logs if cant debug runtime
        Message suitableMessage3 = messagesList.FirstOrDefault(DebugLinq);


        Console.ReadKey();
    }

    private static bool DebugLinq(Message m)
    {
        if (m.Text.Contains("param"))
        {
            // log Text, "param"
            return true;
        }

        if (m.Text.Contains("corr"))
        {
            // log Text, "corr"
            return true;
        }

        return false;
    }

答案 2 :(得分:0)

感谢所有相关人员。都是由于我的注意力不集中以及扩展方法的名称不正确。在项目中使用的一个库中,有一个列表的扩展方法,称为“ FirstOrDefult”。显然,就我而言,此方法始终返回第一个元素。包括LINQ名称空间就可以解决问题,现在一切都按预期运行