C# 如何检查对象';s字段是否存在于给定对象的列表中?
我有两个班,一个叫记录,一个叫位置C# 如何检查对象';s字段是否存在于给定对象的列表中?,c#,.net,list,C#,.net,List,我有两个班,一个叫记录,一个叫位置 public class Record { public string Id { get; set; } } public class Location { public string LocationId { get; set; } public bool isDefault { get; set; } } 现在我需要检查位置列表中是否存在来自记录的给定ID。例如,这是我迄今为止处理的代码。如果当前列表中不存在field.
public class Record
{
public string Id { get; set; }
}
public class Location
{
public string LocationId { get; set; }
public bool isDefault { get; set; }
}
现在我需要检查位置列表中是否存在来自记录的给定ID。例如,这是我迄今为止处理的代码。如果当前列表中不存在field.Id,则应创建一个新位置并将其添加到列表中
foreach (Record field in inputs)
{
locationResponse = await myLocationCmd.GetLocation(locationInput).ConfigureAwait(false);
foreach (Location locations in locationResponse.Locations)
{
if (locations.IsDefault == true)
{
this.BadRequest();
}
else if (locations.IsDefault == false && // Check whether field.Id exists in locationResponse.Locations)
{
locationInput.Verb = CmdletVerb.Set.ToString();
}
else if (locations.IsDefault == false && // Check whether field.Id does not exist in the locationResponse.Locations)
{
locationInput.Verb = CmdletVerb.New.ToString();
}
}
目前我尝试执行
locationResponse.Locations.Contains(field.Id)
,但这会产生一个类型错误。有人知道这样做的正确方法吗?如果我理解正确,您需要在每个对象上循环检查ID
locationResponse.Locations.Contains(field.Id)
给出了一个类型错误,因为这是位置列表,而不是字符串列表
locationResponse = await myLocationCmd.GetLocation(locationInput).ConfigureAwait(false);
foreach (Record field in inputs) {
var idExists = false;
foreach (Location loc in locationResponse.Locations)
idExists = loc.LocationId == field.Id;
if (idExists) break;
}
Console.WriteLine(idExists);
}
不过,对于
输入
列表的大小,我会保持谨慎,因为每个字段都会多次查看相同的位置列表,这是浪费迭代次数基于给定代码的最短修复方法是使用:
bool idExistsInList = locationResponse.Locations.Any(location => location.LocationId == field.Id);
然后您可以使用idExistsInList
和!在您的两条注释中分别列出idExistsInList
但是,还需要做一些进一步的改进:
- 您的代码中有一个bug。内部foreach会一直覆盖相同的值,并且只会有效地保留在
的最后一个循环中设置的值foreach
- 同样的错误也发生在您的外部
上。通过比较两个列表的最后一个元素,可以有效地定义foreach
locationInput.Verb的值,并有效地覆盖所有其他求值
- 一般来说,LINQ优于手动
逻辑。它提高了可读性,减少了模板制作foreach
- 假设这是外部
中唯一的逻辑,也可以使用LINQ简化foreach
- 对于每个输入字段,您获取相同的
。如果没有实际使用特定字段值来获取对象,那么对每个字段执行此操作是没有意义的locationResponse
- 无需进行第三次
评估。当前两次评估失败时,第三次评估总是正确的if
始终可以忽略==true
通常应重构为使用==false
代码>
- 当您总是设置相同的字段/属性,但布尔值决定了您是否将其设置为一个值或另一个值时,是否喜欢使用三元
myBool?valueIfTrue:ValueIfValse
foreach
循环之外提取此逻辑:
var locationResponse = await myLocationCmd.GetLocation(locationInput).ConfigureAwait(false);
if(locationResponse.Locations.Any(location => location.IsDefault))
this.BadRequest();
var locationIds = locationResponse.Locations.Select(location => location.LocationId).ToList();
如何处理foreach
循环尚不清楚,因为我不确定您是否正在尝试查找位置列表中是否有任何字段(=至少一个)匹配,或者是否每个字段都在位置列表中匹配
如果您试图查找位置列表中是否有任何字段(=至少一个)匹配:
bool matchFound = inputs.Any(field => locationIds.Contains(field.Id);
bool matchFound = inputs.All(field => locationIds.Contains(field.Id);
如果要查找位置列表中是否每个字段都有匹配项:
bool matchFound = inputs.Any(field => locationIds.Contains(field.Id);
bool matchFound = inputs.All(field => locationIds.Contains(field.Id);
Any
如果至少有一个字段匹配,则返回true
,All
如果所有字段都匹配,则仅返回true
在任何一种情况下,您都可以继续:
locationInput.Verb = matchFound
? CmdletVerb.Set.ToString()
: CmdletVerb.New.ToString();
这与您的代码相同,但冗余更少,可读性更高。不清楚您的意思。
Id
字段将始终作为对象的属性存在。它可以是null,也可以是空字符串,尽管我试图传达的是列表中的每个Location对象都有一个LocationID。如果列表中已存在与字段ID相比的LocationId,则它将是一个Set命令。如果列表中不存在与位置ID相比的字段ID,则将创建一个新位置并将其添加到列表中。我希望更清楚的是,不要给GetLocation一个ID,然后作为响应的一部分返回,这样所有位置都已经有了正确的ID?GetLocation接受另一个类,当提供一个ID时,它将返回与该ID关联的所有位置。现在在这个特定场景中并不重要。