2009-12-01 24 views
55

Ich möchte eine generische Extension-Methode entwickeln, die die Zeichenfolge in alphabetischer Reihenfolge in aufsteigender Reihenfolge sortieren soll.Wie erstelle ich eine generische Erweiterungsmethode?

ich meine

string[] names = { "Jon", "Marc", "Joel", 
        "Thomas", "Copsey","Konrad","Andrew","Brian","Bill"}; 

var query = names.OrderBy(a => a.Length).ThenBy(a => a); 

Was ist die Art und Weise Generika Erweiterungsmethode zu entwickeln?

Ich habe versucht:

public static class ExtensionOperation 
    { 
     public static T[] AlphaLengthWise<T>(this T[] names) 
     { 
      var query = names.OrderBy(a => a.Length).ThenBy(a => a); 
      return query; 
     } 
    } 

ich erhielt:

Fehler 1: T enthält keine Definition für Länge

Fehler 2: nicht System.Linq.IOrderedEnumerable-T[] umwandeln kann.

+4

Warum sollte es generisch sein, wenn Sie nur Strings arrangieren wollen? – bniwredyc

+6

@bniwredyc Weil 'generic' cool klingt! :) –

+0

Vielen Dank an alle – user215675

Antwort

80

Der erste Fehler ist, weil Length eine Eigenschaft der String Klasse ist, während in der generischen Version der Typ des T-Parameter nicht bekannt ist. Es könnte jeder Typ sein.

Der zweite Fehler ist, weil Sie nur das Abfrageobjekt, aber nicht das tatsächliche Ergebnis zurückgeben. Sie müssen möglicherweise ToArray() anrufen, bevor Sie zurückkehren.

Mit wenig Änderungen könnten Sie mit dieser kommen:

public static class ExtensionOperation 
{ 
    public static IEnumerable<T> AlphaLengthWise<T, L>(
     this IEnumerable<T> names, Func<T, L> lengthProvider) 
    { 
     return names 
      .OrderBy(a => lengthProvider(a)) 
      .ThenBy(a => a); 
    } 
} 

, die Sie mögen diese verwenden:

string[] names = { "Jon", "Marc", "Joel", "Thomas", "Copsey", "Konrad", "Andrew", "Brian", "Bill" }; 
var result = names. AlphaLengthWise(a => a.Length); 
+0

Ich finde mich Techniken wie diesen 'lengthProvider' verwenden viel mit generischem Code. Es ist nur ein weiterer Grund, warum ich Lambda so sehr liebe. : D –

-1

Sie wollen IEnumerable<T> statt T[] verwenden. Ansonsten können Sie Length von T nicht verwenden, da nicht alle Typen eine Length-Eigenschaft besitzen. Sie könnten Ihre Erweiterungsmethode .OrderBy(a => a.ToString().Length)

ändern Wenn Sie wissen, dass Sie immer mit Streichern zu tun haben, verwenden Sie IEnumerable<String> statt IEnumerable<T>, und Sie werden sofort die Length Eigenschaft zugreifen können.

+0

Das Ändern von T [] in IEnumerable erfordert keine Length-Eigenschaft für Elemente. –

+0

wird es sicher nicht. dieser Teil der Antwort bezog sich auf den zweiten Fehler. 'IOrderedEnumerable ' implementiert 'IEnumerable ', so dass dieser Teil des Problems lösen würde. Was die Eigenschaft 'Length' anbelangt, war mein Vorschlag, dass' ToString() 'verwendet wurde, um eine Zeichenkette sicherzustellen, oder, wenn er neu ist, würde er immer mit Zeichenketten arbeiten, um' T' in 'Zeichenkette' zu ​​ändern. –

14

Warum möchten Sie das generisch machen? Verwenden Sie einfach

public static class ExtensionOperations 
{ 
    public static IEnumerable<string> AlphaLengthWise(this string[] names) 
    { 
     var query = names.OrderBy(a => a.Length).ThenBy(a => a); 
     return query; 
    } 
} 
+1

Warum 'string []' und nicht 'IEnumerable '? Sie könnten das '.ToArray()' entfernen und es zurücklassen (wenn ich mich nicht irre). –

2

Ich möchte eine generische Erweiterungsmethode entwickeln, die dann die Saiten alphabetisch ordnen sollte ...

public static class ExtensionOperation 
{ 
    public static IEnumerable<String> AplhaLengthWise(
            this IEnumerable<String> names) 
    { 
     return names.OrderBy(a => a.Length).ThenBy(a => a); 
    } 
} 
3

Warum Sie es generisch sein wollen?

Dies funktioniert nur, wenn T eine Length-Eigenschaft hat und Sie eine Schnittstelle benötigen, um das zu erzwingen.

Außerdem muss T IComparable sein.

1

Kopie von Microsoft tut es:

public static class ExtensionOperation { 
    // Handles anything queryable. 
    public static IOrderedQueryable<string> AlphaLengthWise(this IQueryable<string> names) { 
     return names.OrderBy(a => a.Length).ThenBy(a => a); 
    } 
    // Fallback method for non-queryable collections. 
    public static IOrderedEnumerable<string> AlphaLengthWise(this IEnumerable<string> names) { 
     return names.OrderBy(a => a.Length).ThenBy(a => a); 
    } 
} 
5

Ich glaube, Sie können zum Zwecke der Generika ein wenig verwirrt sein.

Generika sind eine Möglichkeit, eine Klasse oder Methode auf einen bestimmten Typ zuzuschneiden. Eine generische Methode oder Klasse ist so konzipiert, dass sie für beliebige Typ arbeitet. Dies wird am einfachsten in der Klasse List<T> dargestellt, wo es auf eine Liste beliebigen Typs zugeschnitten werden kann. Dies gibt Ihnen die Typ-Sicherheit zu wissen, dass die Liste nur diesen spezifischen Typ enthält.

Ihr Problem wurde entwickelt, um an einem bestimmten Typ, dem Typ string, zu arbeiten. Generika werden kein Problem lösen, das einen bestimmten Typ betrifft.

Was Sie wollen, ist eine einfache (nicht-generic) Erweiterungsmethode:

public static class ExtensionOperations 
{ 
    public static IEnumerable<string> AlphaLengthWise(
     this IEnumerable<string> names) 
    { 
     if(names == null) 
      throw new ArgumentNullException("names"); 

     return names.OrderBy(a => a.Length).ThenBy(a => a); 
    } 
} 

machen das Argument und den Rückgabetyp IEnumerable<string> diese eine nicht-generische Erweiterungsmethode macht die auf jede Art IEnumerable<string> Implementierung anwenden können. Dazu gehören string[], List<string>, ICollection<string>, IQueryable<string> und viele mehr.

Verwandte Themen