C#. Компилятор ругается, не может использовать лямбда выражение, т.к. не может определить тип аргумента. Как обойти?

208
12 сентября 2017, 07:03

От одного и того же класса наследуются несколько других с дополнительными свойствами. Хочу написать универсальную функцию, которая бы работала со списками объектов этих новых классов, т.е. на вход список и параметр, а на выходе элемент списка. Вот упрощенный код того, что примерное хочу реализовать (функция FindByName):

class Animal
{
    public string Name;
}
class Dog:Animal
{
    //some other properties and methods
}
class Cat:Animal
{
    //some other properties and methods
}
class Program
{
    static dynamic FindByName(dynamic list, string name)
    {
        return list.Find(x => x.Name == name);
    }
    static void Main(string[] args)
    {
        List<Dog> dogs = GetListOfDogs();
        //List<Cat> cats = GetListOfCats();
        Dog DogTuzik = FindByName(dogs, "Tuzik");
        //Cat Murka = FindByName(cats, "Murka");
    }
    static List<Dog> GetListOfDogs()
    {
        List<Dog> dogs = new List<Dog>();
        dogs.Add(new Dog{Name="Tuzik"});
        dogs.Add(new Dog{Name="Sharik"});
        return dogs;
    }
}

Компилятор, естественно, ругается:

"Cannot use a lambda expression as an argument to a dynamically dispatched operation without first casting it to a delegate or expression tree type."

На самом деле FindByName гораздо объёмнее, чем в примере, поэтому и хочу убрать его в отдельную процедуру, чтобы сделать код более читаемым.

Поэтому вопрос, как сделать это правильно и может быть более изящно?

Answer 1

Вообще это решается примерно так:

static T FindByName<T>(IEnumerable<T> list, string name) where T : Animal
{
    return list.FirstOrDefault(x => x.Name == name);
}

Зы. Использовать dynamic в C# очень редко требуется, в основном при взаимодействии с какими-то внешними динамически типизированными языками/средами

Answer 2

Можно оставить и dynamic но немного переделать метод в такой:

static dynamic FindByName<T>(dynamic list, string name) where T : Animal
{
    return list is List<T> animals ? animals.Find(x => x.Name == name) : null;
}
READ ALSO
Подключение к базе данных oracle 11g

Подключение к базе данных oracle 11g

ЗдравствуйтеЕсть программа c# ASP

264
Очень длинная арифметика

Очень длинная арифметика

Решил написать программу для сложения больших чисел с использованием длинной арифметики, но Visual Studio выдаёт ошибку "Индекс находился вне...

297
VkNet - Как изъять id человека VK? [С#]

VkNet - Как изъять id человека VK? [С#]

Делаю приложение основанное на vk api (VkNet)Любые операции с профилем другого человека производится только если у вас есть его id

356
Настройка visual studio code. Префиксы переменным

Настройка visual studio code. Префиксы переменным

Как задать OmniSharp правила именования переменных? Хочу к автоматически создаваемым приватным полям добавлять префикс _К примеру, при вызове...

296