Linq不同类型的条件

时间:2015-03-03 06:55:15

标签: c# linq

我有一个从ProfileBase派生的列表。此列表可以包含Profile,DynamicViewProfile的实例,因为它们都是从ProfileBase派生的

但是如果项目类型是DynamicViewProfile,我必须使用NodeName,如果是Profile,那么我应该使用DocName

profileListsForSearch = profileLists.Where(stringToCheck =>
((Profile)stringToCheck).DocName.Contains(searchBar.Text)).ToList();

所以这是用于配置文件,它没关系,但如果列表包含DynamicViewProfile对象,那么我有一个例外,因为docname为null,我需要获取NodeName

我希望我的问题很清楚

3 个答案:

答案 0 :(得分:7)

这里没有什么特别的LINQ - 您基本上使用isas编写与通常相同的代码:

string searchText = searchBar.Text;
profileListsForSearch = profileLists
    .Where(profile =>
        profile is Profile 
        ? ((Profile)profile).DocName.Contains(searchText)
        : ((DynamicViewProfile)profile).NodeName.Contains(searchText))
    .ToList();

假设这些是唯一涉及的两种类型。如果您的列表包含其他类型,则会获得InvalidCastException

然而,这非常难看 - 感觉ProfileBase应该公开一些指示通用名称的属性或方法 - 然后可以实现它以在DocName中返回Profile并且NodeName中的DynamicViewProfile。那么你只需要:

string searchText = searchBar.Text;
profileListsForSearch = profileLists
    .Where(profile => profile.Name.Contains(searchText))
    .ToList();

它在添加ProfileBase的新子类方面也具有前瞻性 - 并且通常更清晰地使用多态性。每当你需要施放 - 特别是有条件地施放到一个或另一个 - 考虑一个共同的方法/属性是否可行,使其更清洁。

答案 1 :(得分:1)

您可以使用is检查对象,并使用ternary运算符在对象上应用条件。

var result = profileLists.Where(stringToCheck =>stringToCheck is Profile ? 
                           ((Profile)stringToCheck).DocName.Contains(searchBar.Text)
                           : ((DynamicViewProfile)stringToCheck).NodeName.Contains(searchBar.Text)).ToList();

答案 2 :(得分:1)

profileListsForSearch = profileLists.Where(p => 
{
  if(p is Profile) return ((Profile)p).DocName.Contains(searchBar.Text));
  if(p is DynamicViewProfile) return ((DynamicViewProfile)p).NodeName.Contains(searchBar.Text)); 
  return false; 
}).ToList();

您可以查看类型。但这实际上只意味着您的类层次结构被破坏了。如果你得出,你永远不应该被迫明确地检查一个类型。

相反,您可以在基类中使用名为FilterText的属性,该属性由基类实现为return DocName;,派生类实现为return NodeName;。然后你的代码看起来像这样:

profileListsForSearch = profileLists.Where(p => p.FilterText.Contains(searchBar.Text)).ToList();