2017-05-28 2 views
0

Ich wollte in meinem Code iienumerable integrieren, so dass es readonly ist, aber ich weiß nicht, wo es möglicherweise implementiert werden soll. Bisher habe ich keine Lösung im Internet gefunden, die mein Problem lösen könnte. Ab sofort habe ich nur List verwendet und wollte in meinem Code imenumerable integrieren. Fühlen Sie sich auch frei, etwas zu empfehlen, wenn Sie schlechte Programmierpraktiken bemerken. HierSo geben Sie eine schreibgeschützte IEnumerable <T> statt einer Liste zurück <T>

ist der Code:

public static List<GuitarItems> GetGuitarItems(string itemCategory) 
{ 
    List<GuitarItems> list = new List<GuitarItems>(); 
    string query = string.Format("SELECT * FROM guitarItems WHERE brand LIKE @brand"); 

    try 
    { 
     conn1.Open(); 
     command1.CommandText = query; 
     command1.Parameters.Add(new SqlParameter("brand", itemCategory)); 
     SqlDataReader reader = command1.ExecuteReader(); 

     while (reader.Read()) 
     { 
      int id = reader.GetInt32(0); 
      string type = reader.GetString(1); 
      string brand = reader.GetString(2); 
      string model = reader.GetString(3); 
      double price = reader.GetDouble(4); 
      string itemimage1 = reader.GetString(5); 
      string itemimage2 = reader.GetString(6); 
      string description = reader.GetString(7); 
      string necktype = reader.GetString(8); 
      string body = reader.GetString(9); 
      string fretboard = reader.GetString(10); 
      string fret = reader.GetString(11); 
      string bridge = reader.GetString(12); 
      string neckpickup = reader.GetString(13); 
      string bridgepickup = reader.GetString(14); 
      string hardwarecolor = reader.GetString(15); 

      GuitarItems gItems = new GuitarItems(id, type, brand, model, price, itemimage1, itemimage2, description, necktype, body, 
       fretboard, fret, bridge, neckpickup, bridgepickup, hardwarecolor); 
      list.Add(gItems); 
     } 
    } 
    finally 
    { 
     conn1.Close(); 
     command1.Parameters.Clear(); 
    } 

    return list; 
} 

Und dann ist hier ein anderer Code:

private void FillPage() 
{ 
    List<GuitarItems> itemList = new List<GuitarItems>(); 
    List<string> itemListPage = new List<string>(); 

    itemList = ConnectionClassGuitarItems.GetGuitarItems(brandType); 

    StringBuilder sb = new StringBuilder(); 

    foreach (GuitarItems gList in itemList) 
    { 
     itemListPage.Add("GuitarItemsIbanezDetails" + (x + 1) + ".aspx"); 

     sb.Append(
       string.Format(
        @" 
        <div class='one-two'> 
         <a href='{3}' runat="'server'"><img runat="'server'" src='{0}'/></a> 
         <div class='content'> 
          <div id='label'>{1} {2}</div> 
         </div> 

       </div>", gList.ItemImage1, gList.Brand, gList.Model, itemListPage[x])); 

     x++; 

    } 


    lblOutput.Text = sb.ToString(); 

} 
+1

Sie haben eine XSS-Sicherheitsanfälligkeit. Und Sie können serverseitige Steuerelemente nicht so erstellen. Sie sollten Datenbindung verwenden. – SLaks

+0

@SLaks - Was passiert, wenn ich einen Code hinzufüge, der die Benutzereingabe aufheben wird, wenn es Script-Tags gibt? wird das helfen, die XSS-Schwachstelle zu beseitigen? –

+0

Nein. Sie müssen etwas über _encoding_ erfahren. – SLaks

Antwort

2

Technisch ein List<T>ist ein IEnumerable<T>, aber ich verstehe, was Sie meinen. Wenn Sie eine List<T> zurückgeben, dann kann diese Liste geändert werden. Sie möchten etwas zurückgeben, das herumgereicht werden kann, ohne dass jemand seinen Inhalt ändert.

Es gibt zwei Dinge, die Sie tun können, um dies zu erreichen. Die erste kann alles sein, was Sie brauchen.

Erstens ändern sich diese

public static List<GuitarItems> GetGuitarItems(string itemCategory) 

dazu:

public static IReadOnlyList<GuitarItems> GetGuitarItems(string itemCategory) 

Wenn Sie das und nichts anderes tun, ist der Rückgabewert der Funktion wird als IReadOnlyList<T> gegossen werden. Diese Schnittstelle erlaubt keine Änderung der Liste. (Es verhindert nicht das Ändern der Eigenschaften von Elementen in der Liste - das ist eine völlig separate Sache.)

List<T> kann als IReadOnlyList<T> umgewandelt werden, so dass Sie nichts anderes in Ihrer Methode ändern müssen. Sie können ein List<GuitarItems> genau so erstellen, wie Sie es jetzt sind, aber es als IReadOnlyList<GuitarItems> zurückgeben, indem Sie einfach den Rückgabetyp der Funktion ändern.

Das führt wahrscheinlich, was Sie brauchen. Wenn Sie jedoch besonders an etwas interessiert sind, das den Inhalt dieser Liste ändert, können Sie noch weiter gehen.

Zum Beispiel, auch wenn das Element aus der Sammlung zurückgegeben, wie IReadOnlyList<GuitarItems> gegossen wird, jemand könnte dies noch tun:

var readonlyList = GetGuitarItems("category"); // returns IReadOnlyList<GuitarItems> 
var list = readonlyList as List<GuitarItems>; 
list.Clear(); // Oh, no - they've modified the list anyway! 

Dies funktioniert, weil das Element aus der Funktion zurück ist eigentlich eine Liste. Niemand sollte versuchen, es als etwas anderes zu verwenden - sie sollten den Typ verwenden, den Sie zurückgeben. Aber aus irgendeinem Grund könnte jemand das tun.

Für zusätzliche Prävention Sie die Rendite Ihrer Funktion daraus ändern könnte:

return list; 

Um dies:

ist
return list.AsReadOnly(); 

Das Ergebnis, dass jetzt bist du kein List<GuitarItems> Besetzung als IReadOnlyList<GuitarItems> Rückkehr . AsReadOnly() erstellt eine neue Kollektion, eine ReadOnlyCollection<GuitarItems> und wirft die als IReadOnlyList<GuitarItems>. Nun zeigt der zurückgegebene Typ nicht nur an, dass die Liste nicht geändert werden kann, sondern sie kann wirklich nicht geändert werden, da es sich um eine schreibgeschützte Sammlung handelt.

Ein guter Weg, um es zu betrachten, ist, dass der Rückgabewert der Methode angeben sollte, was Sie erwarten, dass Verbraucher damit umgehen. Wenn Sie möchten, dass sie eine Liste erhalten, die sie nicht ändern sollten, geben Sie eine IReadOnlyList<T> zurück.


Eine weitere Frage ist, ob Sie eine IEnumerable<T> oder eine IReadOnlyList<T> zurückkehren. IEnumerable<T> ist allgemeiner und stellt auch keine Liste dar, die geändert werden kann. Sie werden sehen, dass es viel öfter verwendet wird. Der Unterschied besteht darin, dass eine IEnumerable<T> eine Abfrage darstellen könnte, die ausgeführt wird. Wenn die zu nummerierenden Elemente mehr als einmal aufgelistet werden, kann dies dazu führen, dass die Abfrage mehrmals ausgeführt wird.

In Ihrem Beispiel oben, wenn Sie geändert List<GuitarItems> zu IEnumerable<GuitarItems> ich ist immer noch wirklich ein List<GuitarItems> Rückkehr, so dass die Liste aufzählt mehrmals nicht wiederholt eine Abfrage ausführen. Aber der Verbraucher, der jetzt ein IEnumerable<GuitarItems> hat, kann nicht wissen, so werden sie, so etwas zu tun:

var items = GetGuitarItems("category").ToList(); 

, um sicherzustellen, dass die Abfrage einmal ausgeführt wird und in eine Liste, die sie aufzählen so oft sie wollen.

Die Rückkehr IReadOnlyList<GuitarItems> lässt sie wissen, dass das, was sie haben, definitiv eine Liste ist, nicht etwas, das jedes Mal abgefragt wird, wenn es aufgezählt wird.

Dies wird offensichtlich, wenn Sie Resharper verwenden. Wenn Sie eine IEnumerable<T> haben und Sie mehr als einmal aufzählen, wird es Sie warnen. Das Objekt könnte wirklich eine Liste oder ein Array sein, aber Sie können das nicht wissen.

+0

Übrigens, ich habe eine Frage .. in dem zweiten Code, den ich oben in privaten void FillPage() -Methode zur Verfügung gestellt habe. Damit es mit Ihrer Lösung funktioniert, habe ich die Liste geändert itemList = new List (); in IReadOnlyList itemList ;. Habe ich es richtig gemacht? weil es scheinbar nicht funktioniert, wenn ich es so versuche -> IReadOnlyList itemList = new IReadOnlyList (); –

0

Was Sie erreichen wollen?

List<T> es ist schon ein IEnumerable<T> weil es implementiert IEnumerable<T> Schnittstelle, so dass Sie Ihre List<T> wie IEnumerable<T> zum Beispiel in Methoden Argumente behandeln können.

Verwandte Themen