检查字符串是否存在于使用 csv 文件中的数据制作的列表中

Check if string exists in list made with data from a csv file

我从 c​​sv 文件导入数据,然后将其存储在列表中 (List<Customer> customers)。通过创建和添加对象将数据添加到列表中。这些对象是使用将文件内容作为参数的构造函数创建的,所有内容都是字符串。据我了解,该列表属于 Customer 类型。我想做一个 if 语句来检查列表中是否存在用户输入(字符串)。

我试过这段代码:

ImportData("CustomerData.csv");

Console.WriteLine("Please provide customer name:");
string customer_Name = Console.ReadLine();

//if (customers.Contains(customer_Name))
bool b = customers.Contains(customer_Name);
//if (customers.Any(customers.Contains(customer_Name)))
if (b)

没有任何效果,我收到错误 CS1503 参数 1:无法从 'string' 转换为 'MyNameSpace.Customer'。我真的不明白这是什么意思。我想也许是因为列表是 <Customer> 类型?我还有一个叫 Customer 的 class。我尝试将列表类型更改为 <string>,但没有帮助。

customersList<T>,其中 T is Customer,您的错误告诉您它无法将 string 转换为 class 类型 Customer,我想你想要的是使用 Linq 来寻找任何 Customer 对象,其中 xxx(客户名称)的 属性 等于用户输入,你可以这样做,您将 somestringproperty 替换为您的 classes 属性 名称的位置:

bool b = customers.Any(a => a.somestringproperty == customer_Name);

List.Contains 要求您提供客户对象。由于您可能没有覆盖 Equals 和 GetHashcode 以允许两个不同的客户实例被视为相等,因此使用它可能毫无意义,因为它需要您在列表中找到您想要的客户实例,然后询问列表如果它包含您找到的实例(您已经知道)

IEnumerable.Any 要求您提供对客户对象进行操作的方法或小函数(通常称为 lambda)和 returns 真或假。这对你的情况更有用

短格式如下:

if (customers.Any(c => c.CustomerName == customer_Name))

c => c.CustomerName == customer_Name 是一个迷你方法 (lambda):

  • c 方法的参数;隐式地是一个客户(因此我将其命名为 c),原因我稍后会讨论
  • => arguments 和 body 之间的分隔符; C# 使用它来理解你正在制作一个 lambda
  • c.CustomerName == customer_Name 解析为布尔值的语句

长格式可能如下所示:

bool SomeMethod(Customer c){
  return c.CustomerName == customer_Name;
}

我们可以将这个长格式缩短为短格式,因为编译器可以找出很多东西:

  • 规则是 Any 需要 return 布尔值,所以我们不需要 bool
  • 这意味着输入参数 c 是一个 Customer 因为列表充满了 Customer
  • 我们可以放弃 { return ... } 因为 C# 有表达式体; “左边的参数,然后是 =>,然后是解析为我们首先提到的 return 值类型的单个语句”意味着我们可以跳过使用大括号和 return关键词
  • 写lamdba时我们不需要给它起名字,因为我们从不在任何地方用名字来引用它;它纯粹体现在它的定义中,只被我们赋予它的一个东西使用,所以它可以保持无名

所以我们的长表逐渐归结为:

//long form: a class level method
bool SomeMethod(Customer c){
  return c.CustomerName == customer_Name;
}

//shorter: expression body; this is still valid C# to put in a class and you could write all your "one line return" methods like this
bool SomeMethod(Customer c) => c.CustomerName == customer_Name;

//shortest: a lambda, this has to be stored in a variable or used in a method call that accepts a lambda - you cannot write this in a class level statemetn because the compiler needs some surrounding context to figure bits of it out
c => c.CustomerName == customer_Name

如果您查看 Any 的文档,它会告诉您必须提供的内容:

解密方法如下:

Any 是一种可以在 IEnumerable 上调用的方法。 List是IEnumerable,所以可以在List上调用Any。列表充满了具有特定类型 TSource 的对象。 TSource 将替换为列表中的任何内容,在本例中为您 Customerthis这个词表示它是一个扩展方法;一个技巧,意味着您可以直接在客户列表上调用它:

//you could do this; call Any and pass customers in
Enumerable.Any(customers, ...)

//but its more normal, readable etc to do this:
customers.Any(...)

在第一个参数上使用 this 允许您像后者一样编写,编译器将理解为前者。它可以让你“让它看起来像是你在你调用它的东西上添加了一个方法,即使你没有”

更有趣的部分是 Func<TSource,bool> 参数。这意味着“一个接受 TSource 和 return 的函数 bool”。请记住,TSource 对于您的 List<Customer> 表示“客户”。

最后提到的是 return 类型,其他所有内容都是方法的参数。如果您看到 Funct<string, int, TSource, DateTime>,则表示“具有 3 个输入参数的函数或方法;stringintTSource(客户)按顺序排列,并且必须 return一个日期时间”。允许提供与此签名者匹配的任何方法。

Any 返回 Funct<TSource, bool>;您必须提供一种方法,该方法采用 TSource(客户,在您的情况下)和 returns a bool.

这匹配:

private string customer_Name = "john" //class level variable

//method that matches the rule "takes a Customer, returns a bool"
bool SomeMethod(Customer c){
  return c.CustomerName == customer_Name;
}

//can be passed to list's Any
customers.Any(SomeMethod)

这个较短的形式也匹配:

customers.Any(c => c.CustomerName == customer_Name)
              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
        also a method that "takes a customer, returns a bool"

Any 将采用您提供的方法并开始循环列表,调用该方法并传入正在循环的当前客户。一旦为真,它就会停止并且 return 为真,因为它发现“任何客户匹配...”为真


I get the error CS1503 Argument 1: cannot convert from 'string' to 'MyNameSpace.Customer'. I don't really understand what it means

希望现在你能看到,如果你看到了:

customers.Any("John")

customers.Any 需要您提供“接受客户和 return 布尔值的方法” a.k.a Func<Customer,bool> - 您不能提供像“John”这样的字符串因为字符串不是 Func<Customer,bool>..

..考虑一下。如果您确实提供了像“John”这样的字符串 - C# 如何知道您要查找的是姓名,而不是地址?

提供方法作为参数而不是提供数据作为参数可能是让您头脑清醒的最重要的事情;为什么 Microsoft 编写的代码接受方法而不是数据?因为简单地说,他们不可能为人们使用 List 的方式的所有变化编写代码,所以他们只是说“我们将循环列表,调用一些我们无法想象的代码——你提供的代码——如果你代码 return 为真,我们将 return 为真

Microsoft 编写 C# 很自然,但缺少只有您才能知道的位 - 因此为什么“像数据一样传递方法”至关重要