我想知道使用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中的内容,即类型,高度和长度,才是可能的目标。
答案 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默认为animal
。
false
表示Type.Contains(keyword)|| false
返回的任何内容。
但是如果添加更多类型,这将变得不灵活。可能是另一种方法?
E.g。使用custom Attibute:
Type.Contains(keyword)
但请注意,对于较大的数据集,这些事情可能效率低下。