2016-11-12 1 views
1

Ich war von diesem Problem verwirrt. Traditionell, wenn ich eine Methode wie folgt schreiben:Warum können Methoden in Enumerable ohne einen Methodenkörper sein?

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

Ich werde einen Compiler-Fehler erhalten, sagte:

'ExtentionMethods.MyClass.myMethod (int, System.Func)' einen Körper erklären müssen weil es nicht abstrakt, extern oder partiell markiert ist

Das ist verständlich. Aber ich schaute auf die Enumerable-Klasse unter dem Namensraum System.Linq. Ich fand, dass alle Methoden keinen Methodenkörper haben, zum Beispiel:

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

Und es gibt keinen irgendwelchen Kompilierungsfehler für ihn. Warum?

Was ist der Grund?

+0

Die zweite Codezeile, die Sie gepostet haben, kompiliert nicht und erzeugt genau den gleichen Fehler wie beim ersten ... Sind Sie sicher, dass Sie tatsächlich versucht haben, diesen Code zu kompilieren (und nicht auf dekompilierten Code oder Dokumentation)? ? –

+2

Sie haben sich die falsche Datei angesehen. Das war eine * Referenz-Assembly *, nicht die Assembly, die zur Laufzeit tatsächlich verwendet wird. Oder möglicherweise die gefälschten dekompilierten Metadaten, die Sie in VS erhalten, wenn Sie den GoTo Definition-Befehl verwenden. Die .NET 4-Referenzassemblys werden nur zur Kompilierungszeit verwendet und enthalten nur die Deklarationen, die Körper sind leer. Die Laufzeitassembly wird vom GAC abgerufen. Achten Sie darauf, diese zu betrachten, können Sie c: \ windows \ microsoft.net \ Assembly nach Belieben navigieren. Oder verwenden Sie die [Referenzquelle] (https://referencesource.microsoft.com/#System.Core/System/Linq/Enumerable.cs577032c8811e20d3). –

Antwort

4

Es liegt daran, dass Sie Metadaten angesehen haben. Metadaten beschreiben nur die Schnittstelle, keine Implementierung.

Sie können Methoden ohne Körper nur in Schnittstellen und abstrakten Klassen schreiben. Aber wenn Sie es verwenden möchten, müssen Sie sie in abgeleiteten Klassen implementieren.

Mehr Informationen über abstrakte Methoden: MSDN abstract methods und Schnittstellen: interface (C# Reference)

1

Konstantin Zadiran bereits gesagt, was Sie wahrscheinlich an, Metadaten suchen.

Eine Methode ohne Körper ist im Wesentlichen eine abstrakte Methode (Sie müssen natürlich auch das Schlüsselwort abstract hinzufügen, um es als eins zu markieren). Nur abstrakte Klassen und Schnittstellen können abstrakte Methoden enthalten. Teilmethoden sind eine andere Art von Methode ohne Körper.

2

I Enumerable Klasse unter Namespace System.Linq sah, fand ich alle Methoden keine Methode Körper

Sie hat nicht gesagt haben, was Implementierung Sie suchen, aber zumindest für CoreFX, es ist nicht wahr. Die Implementierung für System.Linq.Enumerable.Where ist genau dort, wo man es erwarten würde, in 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); 
} 

In der Microsoft .NET Referenzquelle, es ist in System/Linq/Enumerable.cs im System.Core Projekt:

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); 
} 

In Mono war die Implementierung in mcs/class/System.Core/System.Linq/Enumerable.cs, bevor sie swit ched auf die Open-Source-Implementierung von 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); 
} 

Ich konnte nicht eine einzige .NET-Implementierung zu finden, wo die Methode, die Sie zeigte abstrakt ist. In allen Implementierungen, die ich finden konnte, ist es konkret implementiert.

Verwandte Themen