2017-05-28 74 views
0

我想在我的代码中集成ienumerable,以便它是只读的,但我不知道在哪里可能实现它。到目前为止,我还没有在互联网上找到任何可能解决我的问题的解决方案。截至目前,我只使用List,并希望在我的代码中集成ienumerable。另外,如果您发现错误的编码习惯,请随时提出建议。如何返回一个只读的IEnumerable <T>而不是一个列表<T>

下面是代码:

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

然后这里是另一个代码:

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

您有一个XSS漏洞。而且你不能像这样构建服务器端控件。你应该使用数据绑定。 – SLaks

+0

@SLaks - 如果我添加了一个代码,如果有脚本标记,它将取消用户的输入?这将有助于消除XSS漏洞? –

+0

不需要。您需要了解_encoding_。 – SLaks

回答

2

技术上a List<T>IEnumerable<T>,但我理解你的意思。如果您返回List<T>那么该列表可能会被修改。你想要返回可以传递的东西,而不需要任何人修改其内容。

有两件事你可以做到这一点。第一个可能是你所需要的。

首先,改变这一

public static List<GuitarItems> GetGuitarItems(string itemCategory) 

这样:

public static IReadOnlyList<GuitarItems> GetGuitarItems(string itemCategory) 

如果你这样做,没有别的,函数的返回值将被强制转换为IReadOnlyList<T>。该界面不允许修改列表。 (它不会阻止更改列表中项目的属性 - 这完全是另外一回事。)

List<T>可以转换为IReadOnlyList<T>,因此您不必更改方法中的其他任何内容。您可以像现在一样创建List<GuitarItems>,但只需更改函数的返回类型即可将其作为IReadOnlyList<GuitarItems>返回。

这可能会完成你所需要的。但是,如果您特别担心修改列表内容的其他内容,则可以继续。

例如,即使从集合返回的项目被转换为IReadOnlyList<GuitarItems>,有人仍然可以这样做:

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

这将起作用,因为该项目从函数返回实际上是一个列表。没有人应该试图将它作为别的东西 - 他们应该使用你正在返回的类型。但出于某种奇怪的原因,有人可以这样做。

对于额外的预防你可以改变你的函数从该回归:

return list; 

要这样:

return list.AsReadOnly(); 

结果是,现在你没有返回List<GuitarItems>塑像作为IReadOnlyList<GuitarItems>AsReadOnly()创建了一个新的集合,一个ReadOnlyCollection<GuitarItems>并且将作为作为IReadOnlyList<GuitarItems>。现在,不仅返回的类型表明该列表不能被修改,但它确实无法修改,因为它是只读集合。

查看它的一个好方法是该方法的返回值应表明消费者对它的期望。如果您希望他们收到他们不应修改的列表,请返回IReadOnlyList<T>


一个相关的问题是,你是否应该返回IEnumerable<T>IReadOnlyList<T>IEnumerable<T>更通用,也不代表可以更改的列表。你会看到它更经常使用。区别在于IEnumerable<T>可能代表执行的查询。如果要枚举的项目不止枚举一次,则可能导致多次执行查询。

在你上面的例子,如果你改变了List<GuitarItems>IEnumerable<GuitarItems>你还真返回List<GuitarItems>,所以多次枚举列表不多次执行查询。但是,谁现在有一个IEnumerable<GuitarItems>消费者无法知道这一点,所以他们会想要做这样的事情:

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

,以确保查询被执行一次投入,他们可以列举的清单尽可能多的次数。

返回IReadOnlyList<GuitarItems>让他们知道他们拥有的绝对是一个列表,而不是每次枚举时都会被查询的东西。

如果您使用Resharper,这将变得明显。如果你有一个IEnumerable<T>并且你不止一次地列举它,它会警告你。该项目可能确实是一个列表或数组,但你不知道。

+0

顺便说一下,我有一个问题..在第二个代码中,我已经在private void FillPage()方法中提供了上面的代码。为了使它适用于您的解决方案,我更改了列表 itemList = new List ();进入IReadOnlyList itemList ;.我做对了吗?因为它似乎不工作,如果我尝试这样做 - > IReadOnlyList itemList = new IReadOnlyList (); –

0

你想实现什么?

List<T>它已经是一个IEnumerable<T>,因为它实现IEnumerable<T>接口,这样你可以把你的List<T>IEnumerable<T>例如,在方法的参数。

相关问题