Reputation: 28294
I have a function that is declared like so:
public static string MultiWhereToString(List<WhereCondition<T>> whereConditions)
I am trying to pass it a variable called whereAnd
which is delcared like so:
private List<WhereAndCondition<T>> whereAnd = new List<WhereAndCondition<T>>();
WhereAndCondition
is a sub class of WhereCondition
. It is declared like so:
public class WhereAndCondition<T> : WhereCondition<T>, IConditional where T : DatabaseObject
My issue is, if I try to execute the following code:
private List<WhereAndCondition<T>> whereAnd = new List<WhereAndCondition<T>>();
MultiWhereToString(whereAnd);
I get the following error:
Error 3 Argument 1: cannot convert from 'System.Collections.Generic.List<BrainStorm.WhereAndCondition<T>>' to 'System.Collections.Generic.List<BrainStorm.WhereCondition<T>>'
Any ideas on why? I think it has to do with the generics of the WhereCondition
classes.
Upvotes: 1
Views: 222
Reputation: 82554
I would suggest using interfaces:
public static string MultiWhereToString(IEnumerable<ICondition<T>> whereConditions)
This would allow you a lot more freedom when calling this method.
Upvotes: 2
Reputation: 13146
Generics have to be known explicitly at compile time because they are generated.
Why not use:
private List<WhereCondition<T>> whereAnd = new List<WhereCondition<T>>();
So you can still add WhereAndCondition
objects to whereAnd
.
Upvotes: 2
Reputation: 12604
This appears to be a covariance / contravariance issue.
Simplified to this:
public class WhereCondition
{
}
public class WhereAndCondition : WhereCondition
{
}
public class blah
{
public static void Blah()
{
List<WhereAndCondition> whereAnd = new List<WhereAndCondition>();
MultiWhereToString(whereAnd);
}
public static string MultiWhereToString(List<WhereCondition> whereConditions)
{
return null;
}
}
It's not going to work, because the list of WhereAndConditions can't be cast to List of WhereConditions:
Imagine it this way. You've got a list of giraffes, and the method is asking for a list of animals.
Without knowing what they are going to do with the list animals (like try adding a horse) the types are incompatible, but if you change it to something like this:
public static string MultiWhereToString(IEnumerable<WhereCondition> whereConditions)
{
return null;
}
Then the variance can kick in, and give you what you're looking for.
Upvotes: 2
Reputation: 6451
You can replace the entire WhereCondition<T>
in your MultiWhereToString
method with another generic type which is restricted to WhereCondition<T>
.
Replace:
public static string MultiWhereToString(List<WhereCondition<T>> whereConditions)
With:
public static string MultiWhereToString<TType>(List<TType> whereConditions) where TType: WhereCondition<T>
Or alternatively change:
private List<WhereAndCondition<T>> whereAnd = new List<WhereAndCondition<T>>();
to:
private List<WhereCondition<T>> whereAnd = new List<WhereCondition<T>>();
And let inheritance take care of the rest for you.
Upvotes: 2
Reputation: 6112
Your function is defined as taking a WhereCondition List, but you're passing it a WhereAndCondition List:
MultiWhereToString(List<WhereCondition<T>> whereConditions)
private List<WhereAndCondition<T>> whereAnd = new List<WhereAndCondition<T>>();
MultiWhereToString(whereAnd);
List variance has limited supported in .NET 4. See this question.
Upvotes: 2
Reputation: 39950
Given:
class A {}
class A : B {}
An object of List<B>
is not an instance of List<A>
. So you can't cast a List<WhereAndCondition>
to a List<WhereCondition>
. You could use:
MultiWhereToString(whereAnd.OfType<WhereCondition>().ToList());
(There might also be a solution involving the in
and out
variance annotations, but I'm not terribly familiar with them.)
Upvotes: 2