Предисловие: перейдите к редактированию, если хотите получить полное объяснение. Спойлер: Методы расширения — это уловка компилятора, и на самом деле они имеют на один аргумент больше, чем выглядят при их вызове.
Это в разрешении группы методов. По-видимому, компилятор С# не тратит время на то, чтобы выяснить, имеет ли используемый вами метод перегрузки или нет; просто всегда требуется явное приведение. Проверить:
Что такое группа методов в C#?
Вывод метода не работает с группой методов
Группа методов, которая возвращается из reader.GetDoubleOrNull, сужается тем, к чему вы пытаетесь привести ее: GetDoubleOrNull может ссылаться на любое количество перегруженных методов с таким именем. Вы должны явно указать его.
Интересно, что вы даже не можете назначить группу методов переменной с неявным типом по той же причине:
var x = reader.GetDoubleOrNull;
не компилируется, так как требует явного приведения.
Изменить Я почти уверен, что путаница здесь связана с методами расширения:
Проверьте следующий тестовый класс:
public static class Extensions
{
public static List<T> GetList<T>(this IDataReader reader, Func<string, T> del)
{
throw new NotImplementedException();
}
public static double? GetDoubleOrNull(this IDataReader reader, string columnName)
{
throw new NotImplementedException();
}
public static double? blah(this string s)
{
throw new NotImplementedException();
}
}
Вы можете успешно позвонить
var x = reader.GetList(Extensions.blah);
Почему это может быть? blah также является статическим методом расширения, поэтому, основываясь на ваших доказательствах, может показаться, что приведенная выше строка не должна компилироваться. Чтобы еще больше усложнить ситуацию, добавим этот метод:
public static List<T> GetList2<T>(this IDataReader reader, Func<IDataReader, string, T> del)
{
throw new NotImplementedException();
}
Теперь вы можете позвонить
x = reader.GetList2(Extensions.GetDoubleOrNull);
и он будет правильно скомпилирован. Что дает?
Вот ответ: методы расширения на самом деле не добавляют методы к вашим объектам. На самом деле это уловка компилятора, позволяющая вам программировать так, как если бы эти методы были частью ваших классов. . Из здесь:
В вашем коде вы вызываете метод расширения с синтаксисом метода экземпляра. Однако промежуточный язык (IL), сгенерированный компилятором, переводит ваш код в вызов статического метода. Поэтому принцип инкапсуляции на самом деле не нарушается. На самом деле методы расширения не могут получить доступ к закрытым переменным того типа, который они расширяют.
Итак, когда вы звоните
var x = reader.GetDoubleOrNull("myColumnName");
то, что на самом деле компилируется и выполняется, по сути это (совершенно законный вызов, даже если это метод расширения):
var x = Extensions.GetDoubleOrNull(reader, "myColumnName");
Итак, когда вы пытаетесь использовать GetDoubleOrNull в качестве аргумента для Func<string, double?>, компилятор говорит: «Я могу превратить GetDoubleOrNull в Func<IDataReader, string, double?>, потому что у него два аргумента, но я не знаю, как превратить его в Func<string, double?>».
Несмотря на то, что вы вызываете его так, как будто это метод экземпляра IDataReader с одним аргументом, это не так: это просто статический метод с двумя аргументами, который компилятор C# обманул, заставив вас думать, что это часть IDataReader.
person
eouw0o83hf
schedule
07.03.2012
var x = reader.GetList((Func<string, double?>)reader.GetDoubleOrNull)также работает. Resharper помечает приведение как избыточное, но без него компиляция не выполняется. Джон Скит рядом? - person Jacek Gorgoń   schedule 07.03.2012