【问题标题】:Using "IndexOf" on a List<T> of objects在对象列表<T> 上使用“IndexOf”
【发布时间】:2021-07-11 14:38:38
【问题描述】:

在我的 Visual Studio2019 C# 控制台程序(名为“codeTester”)中,我有这个对象:

        public class ipData
        {
            private string ip;
            private string region;
            private string country;

            public ipData(string ip, string region, string country)
            {
                this.ip = ip;
                this.region = region;
                this.country = country;
            }
                    
            public string Ip
            {
                get { return ip; }
                set { ip = value; }
            }

            public string Region
            {
                get { return region; }
                set { region = value; }
            }
            public string Country
            {
                get { return country; }
                set { country = value; }
            }
            
        }

我创建了这个对象的列表并添加了一些数据:

            List<ipData> ipInfo = new List<ipData>();
            ipInfo.Add(new ipData("192.168.0.199", "UT", "USA"));
            ipInfo.Add(new ipData("251.168.0.963", "NB", "CAN"));

现在我想在其中一个字段上搜索列表,所以我要求用户提供要搜索的数据:

            Console.WriteLine("Enter searh criteria: ");
            string searchparam = Console.ReadLine();

接下来我想要找到的项目的索引,如果有的话:

int x = ipInfo.IndexOf(searchparam);

但是这个语句会抛出一个设计时异常:

"参数 1:无法从 'string' 转换为 'codeTester.Program.ipData'"

所以我在这一点上被困了好几个小时,我的所有搜索都没有产生任何相关的信息。我哪里错了?

【问题讨论】:

  • 您要准确搜索什么? IP、地区还是国家? ipInfoList&lt;ipData&gt;,因此您应该将现有的 ipData 实例传递给它以尝试在列表中找到它。看来您实际上是在尝试按字符串值进行搜索,因此 List&lt;T&gt;FindIndex 方法可能更符合您想要做的事情。即便如此,您仍然必须决定您实际尝试搜索的内容以及该搜索应如何在每个元素级别上进行。
  • 尝试在 Linq 的帮助下查询:var index = ipInfo.Select((item, index) =&gt; new {item, index}).FirstOrDefault(r =&gt; r.item?.Ip == searchParam)?.index ?? -1;。这里我假设searchParam 应该与Ip 属性进行比较
  • 我认为这无关紧要,但我正在寻找“地区”。用户输入类似于“UT”,搜索会找到所有带有区域 ==“UT”的元素。很可能将searchparam 与三个字段中的任何一个进行比较。但对于这种情况,它是“区域”。

标签: c# indexof


【解决方案1】:

它不起作用,因为搜索参数的类型应该与列表的元素类型相同。在这种情况下ipData

您可以使用FindIndex,它接受lambda expression 作为参数:

int x =
    ipInfo.FindIndex(ip => ip.Region == searchparam || ip.Country == searchparam);
if (x >= 0) {
    Console.WriteLine($"The IP address is {ipInfo[x]}");
} else {
    Console.WriteLine("not found");
}

或者你可以像这样使用 LINQ:

string ipAddress = ipInfo
    .FirstOrDefault(ip => ip.Region == searchparam || ip.Country == searchparam)?.Ip;

如果没有找到条目,这将返回一个null 字符串。

您也可以让它返回整个记录:

ipData data = ipInfo
    .FirstOrDefault(ip => ip.Region == searchparam || ip.Country == searchparam);
if (data != null) {
    Console.WriteLine(
        $"Country = {data.Country}, Region = {data.Region}, IP = {data.ip}");
}

LINQ 还允许您返回多个结果。例如。您可以像这样返回与一个国家对应的所有数据:

var result = ipInfo.Where(ip => ip.Country == "USA");
foreach (ipData data in result) {
    Console.WriteLine(
        $"Country = {data.Country}, Region = {data.Region}, IP = {data.ip}");
}

C# 命名约定规定类名应以 PascalCase 编写。另一种约定是,长度不超过两个字符的首字母缩写词全部大写 (IP)。根据这些约定,类名应该是IPData

另见:

【讨论】:

  • 谢谢。这正是我所需要的。
  • 啊 - 这里有一个问题。当我使用 FindIndex 方法运行它时,我得到如下输出: Enter searh criteria: UT IP address is codeTester.Program+ipData
  • 如果要直接打印ipData对象,必须override its ToString method
  • 谢谢!这个建议解决了这个问题。
【解决方案2】:

那是因为 IndexOf 在列表中搜索确切的对象。要使其正常工作,您必须改为将 ipData 传递给它。

为此,您应该使用FindFindIndex

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多