在List中使用FindAll,其中包含来自两个派生类

时间:2017-03-24 08:36:01

标签: linq list

我想知道使用FindAll方法是否可以完成以下任务:

我有一个名为Animal的基类。我有两个名为Fish and Dog的派生类。

动物有:

public string Type { get; set; }
public int Height { get; set; }
public int Length { get; set; }
狗有:

public string Color { get; set; }

鱼有:没什么特别的。

我想做这样的事情:

Console.Write("\nEnter keyword to search the farm: ");
string keyword = Console.ReadLine().Trim();

var mySearch = myAnimals.FindAll(p => p.Type.Contains(keyword) || p.Color.Contains(keyword)); 

myAnimals是一个Animal类型的List,包含Fish和Dog的实例。

List<Animal> myAnimals = new List<Animal>();

问题是无法从那里访问Color。只有基类Animal中的内容,即类型,高度和长度,才是可能的目标。

1 个答案:

答案 0 :(得分:1)

您可以使用以下代码:

animals.FindAll(animal => animal.Type.Contains(keyword) || (((animal as Dog)?.Color.Contains(keyword)) ?? false));

那么(((animal as Dog)?.Color?.Contains(keyword)) ?? false)部分实际上做了什么?

让我们把它分成几部分:

(animal as Dog)尝试将动物投射到类型Dog。如果失败,则不会抛出异常,而是返回null

由于我们无法访问Color的{​​{1}}属性(这会产生null),因此我们需要使用NullReferenceException运算符Null-conditional Operator。如果?.不是Color,它只会尝试访问(animal as Dog)。 如果null为空,则整个表达式变为(animal as Dog)。 与null相同的颜色本身可以是Color?.Contains()

由于我们需要在null之后的布尔表达式而||不是布尔值,我们还使用null运算符aka Null-coalescing Operator。如果左侧的表达式为??,请使用右侧的值。否则使用左侧的值。

这意味着如果null是具有Color属性并且此属性不为null的Dog,请使用animal的返回值,该值为true或false。 否则,如果Contains(keyword)不是Dog,则Color默认为animalfalse表示Type.Contains(keyword)|| false返回的任何内容。

但是如果添加更多类型,这将变得不灵活。可能是另一种方法?

E.g。使用custom Attibute

Type.Contains(keyword)

但请注意,对于较大的数据集,这些事情可能效率低下。