views:

169

answers:

6

I am porting some Java code to C# and I ran across this:

List<?>

As I understand it this is a List of type Unknown. As a result I can dictate the type elsewhere (at runtime? I'm not sure).

What is the fundamental equivalent in C#?

+7  A: 

If you want a list that can hold anything, you can use a List<object> or an ArrayList.

If you want a strongly-typed list that holds an unknown type, you should make a generic class or method and use a List<T>.

For more specific advice, please provide more detail.

SLaks
List<T> is not an unknown type. It is type T. ? in java is something different.
serg10
@Serg: That's why I said **If**.
SLaks
A: 

You could just use

List<object>

Rohan West
This does not work. `List<object>` is not equivalent to Java's `List<?>`, which is an implementation of contravariance, which C# 4 still does not support (only for interfaces and delegates)
Matt Greer
A: 

I think the questioner wants to convert something like this

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

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

into C# equivalent.

The following code won't work, because it only accept List<Object>, not List<Foo>

int size2(List<Object> list)
{
    return 2*list.size(); 
}
irreputable
In your scenario this is going to work:int size2<T>(List<T> list){ return 2*list.Count;}
Edgar Sánchez
+3  A: 

I think the best match to Java's List<?> would be C# 4.0 IEnumerable<out T> If you have a method that takes List<?> than you can call it with List<Object> and List<String> like so:

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<T> interface is actually IEnumerable<out T>, which means that if, say, R derives from T, IEnumerable<T> can be assigned to from IEnumerable<R>.

So, all you have to do is make your doSomething into DoSomething and have accept IEnumerable<T> parameter:

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
}

EDIT: If C# 4.0 is not available, you can always fall back to either untyped IEnumerable or IList.

Igor Zevaka
C#4.0 uses declaration-site variance, whereas Java is use-site. Use-site makes more sense where "read-write" interfaces are common.
Tom Hawtin - tackline
+1  A: 

It sounds like IList is what you're looking for. It's a generic interface for lists, meaning you'll have to cast anything that comes out and be careful what you put in.

Gabe
+1  A: 

Firstly, as mentioned elsewhere, the unbounded wildcard parameterized type is not the same as Object. Generics are not covariant. So in the OP's Java example List<?> is not the same as List<Object>. As an example,

// 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

The only real use case for List<?> in Java is when interacting with legacy non generic collections. It allows you to avoid unchecked conversion warnings from the compiler.

C# does not have this use case. C# generics were not implemented using erasure. There is no backwards compatibility between the generic and non-generic collections in .net - they co-exist in the core .net libraries. That is different from Java where the generic version of the collections api replaced the non generic version at JDK 1.5.

So I don't think there is a reason to want this construct in C#, and there is no direct equivalent that behaves in the same way.

serg10