6
private static void PrintEachItemInList<T>(T anyList) 
Where T:System.Collections.Generic.List<T>
{    
    foreach (var t in T)
    {
        //Do whatever
    }
}

在上面的代码(这是错误的)中,我想做的只是设置T一个 List 的约束。

目的不是让这个示例工作,目的是了解如何设置类型为列表的约束?我是仿制药的业余爱好者,正在努力解决问题:(

4

5 回答 5

7

也许你想要两个类型参数,如:

private static void PrintEachItemInList<TList, TItem>(TList anyType) 
  where TList : System.Collections.Generic.List<TItem>

如果您使用实际派生自List<>. 如果您想要任何充当列表的东西,请考虑改为限制到界面 IList<>。然后它将适用于List<>、一维数组和实现接口的自定义类(但不一定派生自List<>)。

编辑:正如评论所指出的,这种方法使用起来很麻烦,因为编译器不会推断这两个类型参数,所以在调用方法时必须明确给出它们。

考虑只使用:

private static void PrintEachItemInList<TItem>(List<TItem> anyType) 

因为从 a 派生的任何东西都List<>可以分配给List<>,所以可以使用派生类作为参数调用该方法,并且在许多情况下TItem,编译器可以自动推断类型。

还是考虑用接口IList<>

如果您想要做的只是从列表中读取,请使用IReadOnlyList<TItem>而不是IList<TItem>. 这向来电者发出信号,表明您不会更改他的列表。调用时仍然不需要强制转换语法,例如:PrintEachItemInList(new[] { 2, 3, 5, 7, });. 该类型IReadOnlyList<>是 .NET 4.5 版中的新类型。

如果您只想从列表中读取,并且您不想使用索引器(否anyType[idx]),并且您不想使用.Count属性,实际上您只想foreach通过列表, 使用IEnumerable<TItem>. 再次,您表示您不会更改人员列表。

两者IReadOnlyList<>和在它们的通用参数(类型参数)中IEnumerable<>都是协变的。

于 2013-02-11T16:56:50.587 回答
6

将您的输入参数声明为IList<T>. 如果你想让你的输入序列尽可能抽象 - 使用IEnumerable<T>而不是IList<T>

private static void PrintEachItemInList<T>(IList<T> sequence)
{
    foreach (T element in sequence)
    {
        //Do whatever
    }
} 
于 2013-02-11T16:55:19.540 回答
3

您的函数应该只接受一个列表,并且您不需要约束:

private static void PrintEachItemInList<T>(IList<T> list) 
{
    foreach (var t in list)
    {
        //Do whatever
    }
}

但是,如果您只想迭代列表,则可以通过将参数类型更改为以下基本接口之一来使代码更通用:

  • IEnumerable<T>- 允许foreach
  • IReadOnlyCollection- 与上面相同,并提供集合中元素的数量
  • IReadOnlyList- 与上面相同,并允许通过索引访问元素
  • ICollection<T>-IEnumerable<T>提供元素计数和添加和删除元素的方法
  • IList<T>- 与上面相同,允许您按索引添加和删除元素
于 2013-02-11T16:55:30.537 回答
2

如果您想使用参数多态性来表达该约束,则在 c# 中您需要两个类型参数(因为您没有获得高阶类型):

private static void PrintEachItemInList<X, T>(X anyType) where X:System.Collections.Generic.List<T>
{

             foreach (var t in anyType)
            {
                Console.WriteLine(t.ToString());
            }
}

但是你需要这样调用:

PrintEachItemInList<List<string>,string>(new List<string>() {"a", "b"});
于 2013-02-11T17:03:18.870 回答
1

你通常会这样写:

private static void PrintEachItemInList<T>(List<T> anyType)
{
  // do work
}

但是,在这种情况下,我建议IEnumerable<T>改用:

private static void PrintEachItemInList<T>(IEnumerable<T> anyType)
{
  // do work
}

这仍然允许您使用foreach,但允许您的方法更加灵活,因为它可以工作List<T>,而且任何其他实现IEnumerable<T>. 如果您必须在方法中包含列表语义,则可以使用IList<T>,但您的示例代码(和方法名称)建议IEnumerable<T>会更合适。

于 2013-02-11T16:55:26.430 回答