我可以翻译成中文:C#中是否可以有未类型化的集合?

10

我正在将一些Java代码移植到C#,并遇到了这个问题:

List<?>

据我所知,这是一个类型为UnknownList。因此,我可以在其他地方(在运行时?我不确定)指定类型。

C#中的基本相当之物是什么?


1
问题是:这真的是一个好主意吗?还是你最好使用类型安全? - Ed S.
5
List<Object> 不是一个相关的答案。如果一个方法接受 List<?> 参数,它可以接受所有类型的 List,比如 List<String>、List<Integer>。如果参数是 List<Object>,它就不能工作。 - irreputable
能否提供一些上下文信息?这个声明是在哪里和用于何种目的? - Édgar Sánchez Gordón
6个回答

7

我认为与Java的List<?>最匹配的是C# 4.0的IEnumerable<out T>。如果您有一个接受List<?>的方法,那么您可以使用List<Object>List<String>来调用它:

List<Object> objList = new List<Object>();
List<String> strList = new List<String>();

doSomething(objList); //OK
doSomething(strList); //OK

public void doSomething(List<?> theList) {
 ///Iterate through list
}

C# 4.0中的IEnumerable接口实际上是IEnumerable,这意味着如果R从T派生出来,IEnumerable可以从IEnumerable分配。因此,您只需要将doSomething更改为DoSomething,并接受IEnumerable参数即可。
List<Object> objList = new List<Object>();
List<String> strList = new List<String>();

DoSomething(objList); //OK
DoSomething(strList); //OK

public void DoSomething<T>(IEnumerable<T> theList) {
 ///Iterate through list
}

编辑:如果没有C# 4.0版本,您始终可以回退到不带类型的IEnumerableIList


C#4.0使用声明处协变性,而Java使用的是使用处。在常见的“读写”接口中,使用处更加合理。 - Tom Hawtin - tackline

5
如果您需要一个可以容纳任何类型的列表,您可以使用 List<object> 或者 ArrayList
如果您需要一个强类型列表来保存未知类型,您应该创建一个泛型类或方法,并使用 List<T>
如果需要更具体的建议,请提供更多细节。

List<T> 不是未知类型,它是类型 T。在 Java 中,问号是另一种东西。 - serg10
@Serg:这就是为什么我说“如果”。 - SLaks

3
首先,如其他地方所述,未限定通配符参数化类型与Object不同。泛型不是协变的。因此,在OP的Java示例中,List与List不同。例如,
// Unbounded wildcard type is not the same as Object...
List<?> unboundedList = new ArrayList<Object>(); 
List<Object> objectList = new ArrayList<Object>();
unboundedList = objectList;    // no problems
objectList = unboundedList;    // whoops! compile time error

在Java中,List<?>的唯一真正用例是与遗留的非泛型集合交互。它允许您避免编译器的未检查转换警告。
C#没有这种用例。 C#泛型不是使用擦除实现的。 .net中的泛型和非泛型集合之间没有向后兼容性——它们共存于核心.net库中。这与Java不同,在JDK 1.5中,集合API的泛型版本取代了非泛型版本。 因此,我认为在C#中没有理由想要这个结构,并且没有直接等效的行为方式。

1

听起来你需要的是 IList。它是一个用于列表的通用接口,这意味着你必须对输出进行强制转换,并小心地处理输入。


0

我认为问询者想要将类似这样的东西转换

int size2(List<?> list)
{
    return 2*list.size(); 
}

List<Foo> list = ...
size2(list);

转换为C#等效代码。

以下代码将无法工作,因为它只接受 List<Object>,而不是 List<Foo>

int size2(List<Object> list)
{
    return 2*list.size(); 
}

在您的情况下,这将起作用:int size2<T>(List<T> list) { return 2*list.Count; } - Édgar Sánchez Gordón

-1
你可以直接使用

List<object>


1
这行代码无法工作。List<object> 与 Java 的 List<?> 不等价,后者是逆变的实现,而 C# 4 仍不支持(只支持接口和委托)。 - Matt Greer

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接