Причины для указания универсальных типов в методах расширения LINQ - PullRequest
1 голос
/ 29 июня 2011

Просто из любопытства:

Многие методы расширения LINQ существуют как в общем, так и в неуниверсальном вариантах, например, Any и Any<>, Where и Where<> и т. Д. При написании запросов я обычно использую неуниверсальные варианты, и это работает хорошо.

Какие бывают случаи, когда нужно использовать универсальные методы?

--- редактировать ---

P.S .: Мне известно о том, что внутренне вызываются только общие методы, и компилятор пытается разрешить содержимое общих скобок <> во время компиляции. Мой вопрос, скорее, в каких случаях нужно явно указывать тип, а не полагаться на интуицию компилятора?

Ответы [ 2 ]

5 голосов
/ 29 июня 2011

Всегда. Компилятор C # достаточно умен, чтобы определить, какой тип метода основан на параметрах. Это важно, когда тип является анонимным и поэтому не имеет имени.

obj.SomeMethod(123); //these calls are the same
obj.SomeMethod<int>(123);

obj.SomeMethod(new { foo = 123 }); //what type would I write here?!

Редактировать: Для ясности, вы всегда вызываете универсальный метод. Это выглядит как неуниверсальный метод, так как компилятор и Intellisense умны.

Edit: к вашему обновленному вопросу, вы бы хотели быть конкретным, если вы хотите использовать тип, который не является типом объекта, который вы передаете. Есть два таких случая:

  1. Если параметр реализует интерфейс, и вы хотите работать с этим интерфейсом, а не с конкретным типом, то вы должны указать интерфейс:

    obj.DoSomething<IEnumerable<Foo>>( new List<Foo>() );
    
  2. Если параметр неявно преобразуется в другой тип, и вы хотите использовать второй тип, вам следует указать его:

    obj.DoSomethingElse<long> ( 123 ); //123 is actually an int, but convertible to long
    

С другой стороны, если вам нужен приведение для выполнения преобразования (или вы все равно его вставляете), тогда вам не нужно указывать:

obj.DoYetAnotherThing( (Transformed)new MyThing() ); // calls DoYetAnotherThing<Transformed>
3 голосов
/ 29 июня 2011

Один пример, с которым я столкнулся сегодня:

ObjectSet<User> users = context.Users;
var usersThatMatch = criteria.Aggregate(users, (u, c) => u.Where(c));

Приведенный выше код не будет работать, поскольку метод .Where не возвращает ObjectSet<User>. Вы можете обойти это одним из двух способов. Я мог бы вызвать .AsQueryable() для пользователей, чтобы убедиться, что он строго типизирован как IQueryable, или я мог бы передать аргументы определенного типа в метод Aggregate:

criteria.Aggregate<Func<User, bool>, IEnumerable<User>>(
    PersonSet, (u, c) => u.Where(c));

Другая пара более распространенных примеров - это методы Cast и OfType, которые не могут определить, какой тип вам нужен, и во многих случаях в первую очередь вызываются для неуниверсальной коллекции.

В общем, люди, которые разрабатывали методы LINQ, старались изо всех сил избегать необходимости использовать явные типы в этих универсальных методах, и по большей части вам это не нужно. Я бы сказал, что лучше знать, что это вариант, но избегайте этого, если не считаете это необходимым.

...