2016-11-12 3 views
1

Я был смущен этой проблемой. Традиционно, если я пишу метод, как это:Почему методы в Enumerable могут быть без тела метода?

public static class MyClass 
{ 
    public static int myMethod(this int x, Func<int, bool> evaluate); 
} 

Я получаю ошибку компиляции, сказал:

'ExtentionMethods.MyClass.myMethod (интермедиат, System.Func)' должен объявить тело поскольку он не обозначен как абстрактный, внешний или частичный

Это понятно. Но я посмотрел класс Enumerable в пространстве имен System.Linq. Я обнаружил, что все методы не имеют тела метода, например:

public static IEnumerable<TSource> Where<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate); 

И нет никакой ошибки компиляции. Зачем?

В чем причина?

+0

Вторая строка кода, который вы отправили, не скомпилирует и не производит точно такую ​​же ошибку, которую вы получите для первой ... Вы действительно пытались скомпилировать этот код (и не смотрели на какой-то декомпилированный код или документацию) ? –

+2

Вы посмотрели не тот файл. Это была * эталонная сборка *, а не сборка, которая фактически используется во время выполнения. Или, возможно, поддельные декомпилированные метаданные, которые вы получите в VS, когда используете команду GoTo Definition. Сборочные сборки .NET 4 используются только во время компиляции и содержат только объявления, тела пустые. Среда выполнения выполняется из GAC. Обязательно посмотрите на них, вы можете перемещаться по c: \ windows \ microsoft.net \ по желанию. Или используйте [Reference Source] (https://referencesource.microsoft.com/#System.Core/System/Linq/Enumerable.cs,577032c8811e20d3). –

ответ

4

Это потому, что вы посмотрели метаданные. Метаданные просто описывают интерфейс, а не реализацию.

Вы можете писать методы без тела только в интерфейсах и абстрактных классах. Но если вы хотите его использовать, вам необходимо реализовать их в производных классах.

Более подробная информация об абстрактных методах: MSDN abstract methods и интерфейсов: interface (C# Reference)

1

Константина Задираном уже сказал вам, что вы, вероятно, глядя, метаданные.

Метод без тела по существу является абстрактным методом (конечно, вы должны также добавить ключевое слово abstract, чтобы отметить его как один). Только абстрактные классы и интерфейсы могут содержать абстрактные методы. Частичные методы - это другой тип метода без тела.

2

Я смотрел Enumerable класс под пространством имен System.Linq, я нашел все методы не имеют тела метода

Вы не сказали, что реализация вы смотрите, но, по крайней мере, для CoreFX, это не правда. Реализация для System.Linq.Enumerable.Where именно там, где можно было бы ожидать его в src/System.Linq/src/System/Linq/Where.cs:

public static IEnumerable<TSource> Where<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate) 
{ 
    if (source == null) 
    { 
     throw Error.ArgumentNull(nameof(source)); 
    } 

    if (predicate == null) 
    { 
     throw Error.ArgumentNull(nameof(predicate)); 
    } 

    Iterator<TSource> iterator = source as Iterator<TSource>; 
    if (iterator != null) 
    { 
     return iterator.Where(predicate); 
    } 

    TSource[] array = source as TSource[]; 
    if (array != null) 
    { 
     return new WhereArrayIterator<TSource>(array, predicate); 
    } 

    List<TSource> list = source as List<TSource>; 
    if (list != null) 
    { 
     return new WhereListIterator<TSource>(list, predicate); 
    } 

    return new WhereEnumerableIterator<TSource>(source, predicate); 
} 

В Microsoft .NET Reference Source, то в System/Linq/Enumerable.cs в System.Core проекте:

public static IEnumerable<TSource> Where<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate) { 
    if (source == null) throw Error.ArgumentNull("source"); 
    if (predicate == null) throw Error.ArgumentNull("predicate"); 
    if (source is Iterator<TSource>) return ((Iterator<TSource>)source).Where(predicate); 
    if (source is TSource[]) return new WhereArrayIterator<TSource>((TSource[])source, predicate); 
    if (source is List<TSource>) return new WhereListIterator<TSource>((List<TSource>)source, predicate); 
    return new WhereEnumerableIterator<TSource>(source, predicate); 
} 

В Mono реализация была в mcs/class/System.Core/System.Linq/Enumerable.cs, прежде чем они переключаются Чед с открытым исходным кодом реализации от Microsoft:

public static IEnumerable<TSource> Where<TSource> (this IEnumerable<TSource> source, Func<TSource, bool> predicate) 
{ 
    Check.SourceAndPredicate (source, predicate); 

    // It cannot be IList<TSource> because it may break on user implementation 
    var array = source as TSource[]; 
    if (array != null) 
     return CreateWhereIterator (array, predicate); 

    return CreateWhereIterator (source, predicate); 
} 

Мне не удалось найти ни одной реализации .NET, где метод вы показали абстрактно. Во всех реализациях, которые я мог найти, он конкретно реализован.

Смежные вопросы