Problem understanding covariance contravariance with generics in C#
up vote
74
down vote
favorite
I can't understand why the following C# code doesn't compile.
As you can see, I have a static generic method Something with an IEnumerable<T>
parameter (and T
is constrained to be an IA
interface), and this parameter can't be implicitly converted to IEnumerable<IA>
.
What is the explanation? (I don't search for a workaround, just to understand why it doesn't work).
public interface IA { }
public interface IB : IA { }
public class CIA : IA { }
public class CIAD : CIA { }
public class CIB : IB { }
public class CIBD : CIB { }
public static class Test
{
public static IList<T> Something<T>(IEnumerable<T> foo) where T : IA
{
var bar = foo.ToList();
// All those calls are legal
Something2(new List<IA>());
Something2(new List<IB>());
Something2(new List<CIA>());
Something2(new List<CIAD>());
Something2(new List<CIB>());
Something2(new List<CIBD>());
Something2(bar.Cast<IA>());
// This call is illegal
Something2(bar);
return bar;
}
private static void Something2(IEnumerable<IA> foo)
{
}
}
Error I get in Something2(bar) line:
Argument 1: cannot convert from 'System.Collections.Generic.List<T>'
to 'System.Collections.Generic.IEnumerable<ConsoleApp20.Program.IA>'
c# covariance
New contributor
add a comment |
up vote
74
down vote
favorite
I can't understand why the following C# code doesn't compile.
As you can see, I have a static generic method Something with an IEnumerable<T>
parameter (and T
is constrained to be an IA
interface), and this parameter can't be implicitly converted to IEnumerable<IA>
.
What is the explanation? (I don't search for a workaround, just to understand why it doesn't work).
public interface IA { }
public interface IB : IA { }
public class CIA : IA { }
public class CIAD : CIA { }
public class CIB : IB { }
public class CIBD : CIB { }
public static class Test
{
public static IList<T> Something<T>(IEnumerable<T> foo) where T : IA
{
var bar = foo.ToList();
// All those calls are legal
Something2(new List<IA>());
Something2(new List<IB>());
Something2(new List<CIA>());
Something2(new List<CIAD>());
Something2(new List<CIB>());
Something2(new List<CIBD>());
Something2(bar.Cast<IA>());
// This call is illegal
Something2(bar);
return bar;
}
private static void Something2(IEnumerable<IA> foo)
{
}
}
Error I get in Something2(bar) line:
Argument 1: cannot convert from 'System.Collections.Generic.List<T>'
to 'System.Collections.Generic.IEnumerable<ConsoleApp20.Program.IA>'
c# covariance
New contributor
7
Possible duplicate of Why covariance and contravariance do not support value type
– Dirk
2 days ago
9
You have not restrictedT
to reference types. If you use the conditionwhere T: class, IA
then it should work. The linked answer has more details.
– Dirk
2 days ago
1
@Dirk I don't think this should be flagged as a duplicate. While it's true that the concept problem here is a covariance/contravariance problem in the face of value types, the specific case here is "what does this error message mean" as well as the author not realizing merely including "class" fixes his issue. I believe future users will search for this error message, find this post, and leave happy. (As I often do.)
– Reginald Blue
2 days ago
You can also reproduce the situation by simply sayingSomething2(foo);
directly. Going around.ToList()
to get aList<T>
(T
is your type parameter declared by the generic method) is not needed to understand this (aList<T>
is anIEnumerable<T>
).
– Jeppe Stig Nielsen
yesterday
add a comment |
up vote
74
down vote
favorite
up vote
74
down vote
favorite
I can't understand why the following C# code doesn't compile.
As you can see, I have a static generic method Something with an IEnumerable<T>
parameter (and T
is constrained to be an IA
interface), and this parameter can't be implicitly converted to IEnumerable<IA>
.
What is the explanation? (I don't search for a workaround, just to understand why it doesn't work).
public interface IA { }
public interface IB : IA { }
public class CIA : IA { }
public class CIAD : CIA { }
public class CIB : IB { }
public class CIBD : CIB { }
public static class Test
{
public static IList<T> Something<T>(IEnumerable<T> foo) where T : IA
{
var bar = foo.ToList();
// All those calls are legal
Something2(new List<IA>());
Something2(new List<IB>());
Something2(new List<CIA>());
Something2(new List<CIAD>());
Something2(new List<CIB>());
Something2(new List<CIBD>());
Something2(bar.Cast<IA>());
// This call is illegal
Something2(bar);
return bar;
}
private static void Something2(IEnumerable<IA> foo)
{
}
}
Error I get in Something2(bar) line:
Argument 1: cannot convert from 'System.Collections.Generic.List<T>'
to 'System.Collections.Generic.IEnumerable<ConsoleApp20.Program.IA>'
c# covariance
New contributor
I can't understand why the following C# code doesn't compile.
As you can see, I have a static generic method Something with an IEnumerable<T>
parameter (and T
is constrained to be an IA
interface), and this parameter can't be implicitly converted to IEnumerable<IA>
.
What is the explanation? (I don't search for a workaround, just to understand why it doesn't work).
public interface IA { }
public interface IB : IA { }
public class CIA : IA { }
public class CIAD : CIA { }
public class CIB : IB { }
public class CIBD : CIB { }
public static class Test
{
public static IList<T> Something<T>(IEnumerable<T> foo) where T : IA
{
var bar = foo.ToList();
// All those calls are legal
Something2(new List<IA>());
Something2(new List<IB>());
Something2(new List<CIA>());
Something2(new List<CIAD>());
Something2(new List<CIB>());
Something2(new List<CIBD>());
Something2(bar.Cast<IA>());
// This call is illegal
Something2(bar);
return bar;
}
private static void Something2(IEnumerable<IA> foo)
{
}
}
Error I get in Something2(bar) line:
Argument 1: cannot convert from 'System.Collections.Generic.List<T>'
to 'System.Collections.Generic.IEnumerable<ConsoleApp20.Program.IA>'
c# covariance
c# covariance
New contributor
New contributor
edited 2 days ago
Peter Mortensen
13.2k1983111
13.2k1983111
New contributor
asked 2 days ago
BenLaz
44847
44847
New contributor
New contributor
7
Possible duplicate of Why covariance and contravariance do not support value type
– Dirk
2 days ago
9
You have not restrictedT
to reference types. If you use the conditionwhere T: class, IA
then it should work. The linked answer has more details.
– Dirk
2 days ago
1
@Dirk I don't think this should be flagged as a duplicate. While it's true that the concept problem here is a covariance/contravariance problem in the face of value types, the specific case here is "what does this error message mean" as well as the author not realizing merely including "class" fixes his issue. I believe future users will search for this error message, find this post, and leave happy. (As I often do.)
– Reginald Blue
2 days ago
You can also reproduce the situation by simply sayingSomething2(foo);
directly. Going around.ToList()
to get aList<T>
(T
is your type parameter declared by the generic method) is not needed to understand this (aList<T>
is anIEnumerable<T>
).
– Jeppe Stig Nielsen
yesterday
add a comment |
7
Possible duplicate of Why covariance and contravariance do not support value type
– Dirk
2 days ago
9
You have not restrictedT
to reference types. If you use the conditionwhere T: class, IA
then it should work. The linked answer has more details.
– Dirk
2 days ago
1
@Dirk I don't think this should be flagged as a duplicate. While it's true that the concept problem here is a covariance/contravariance problem in the face of value types, the specific case here is "what does this error message mean" as well as the author not realizing merely including "class" fixes his issue. I believe future users will search for this error message, find this post, and leave happy. (As I often do.)
– Reginald Blue
2 days ago
You can also reproduce the situation by simply sayingSomething2(foo);
directly. Going around.ToList()
to get aList<T>
(T
is your type parameter declared by the generic method) is not needed to understand this (aList<T>
is anIEnumerable<T>
).
– Jeppe Stig Nielsen
yesterday
7
7
Possible duplicate of Why covariance and contravariance do not support value type
– Dirk
2 days ago
Possible duplicate of Why covariance and contravariance do not support value type
– Dirk
2 days ago
9
9
You have not restricted
T
to reference types. If you use the condition where T: class, IA
then it should work. The linked answer has more details.– Dirk
2 days ago
You have not restricted
T
to reference types. If you use the condition where T: class, IA
then it should work. The linked answer has more details.– Dirk
2 days ago
1
1
@Dirk I don't think this should be flagged as a duplicate. While it's true that the concept problem here is a covariance/contravariance problem in the face of value types, the specific case here is "what does this error message mean" as well as the author not realizing merely including "class" fixes his issue. I believe future users will search for this error message, find this post, and leave happy. (As I often do.)
– Reginald Blue
2 days ago
@Dirk I don't think this should be flagged as a duplicate. While it's true that the concept problem here is a covariance/contravariance problem in the face of value types, the specific case here is "what does this error message mean" as well as the author not realizing merely including "class" fixes his issue. I believe future users will search for this error message, find this post, and leave happy. (As I often do.)
– Reginald Blue
2 days ago
You can also reproduce the situation by simply saying
Something2(foo);
directly. Going around .ToList()
to get a List<T>
(T
is your type parameter declared by the generic method) is not needed to understand this (a List<T>
is an IEnumerable<T>
).– Jeppe Stig Nielsen
yesterday
You can also reproduce the situation by simply saying
Something2(foo);
directly. Going around .ToList()
to get a List<T>
(T
is your type parameter declared by the generic method) is not needed to understand this (a List<T>
is an IEnumerable<T>
).– Jeppe Stig Nielsen
yesterday
add a comment |
2 Answers
2
active
oldest
votes
up vote
172
down vote
accepted
The error message is insufficiently informative, and that is my fault. Sorry about that.
The problem you are experiencing is a consequence of the fact that covariance only works on reference types.
Now, you're probably saying "but IA is a reference type" right now. Yes, it is. But you didn't say that T is IA. You said that T is a type which implements IA, and a value type can implement an interface.
If you want covariance to work you have to tell the compiler that the type parameter is a reference type with the class
constraint as well as the IA
interface constraint.
The error message really should say that the conversion is not possible because covariance requires a guarantee of reference-type-ness, since that is the fundamental problem.
2
Why you said it's your fault?
– user4951
2 days ago
56
@user4951: Because I implemented all of the conversion checking logic including the error messages.
– Eric Lippert
2 days ago
10
Admits fault and offers solution. IMO, +1 to Eric Lippert's personal rep.
– BurnsBA
2 days ago
1
@PeterA.Schneider: I appreciate that. But one of my primary goals for designing the error reporting logic in Roslyn was in particular to capture not just what rule was violated, but furthermore, to identify the "root cause" where possible. For example, what should the error message be forcustomers.Select(c=>c.FristName)
? The C# specification is very clear that this is an overload resolution error: the set of applicable methods named Select that can take that lambda is empty. But the root cause is thatFirstName
has a typo.
– Eric Lippert
yesterday
2
@PeterA.Schneider: I did a lot of work to ensure that scenarios involving generic type inference and lambdas used the appropriate heuristics to deduce what error message was likely to best help the developer. But I did a far less good job on the conversion error messages, particularly where variance was concerned. I've always regretted that.
– Eric Lippert
yesterday
|
show 1 more comment
up vote
14
down vote
I just wanted to complement Eric's excellent insider answer with a code example for those that may not be that familiar with generic constraints.
Change Something
's signature like this: The class
constraint has to come first.
public static IList<T> Something<T>(IEnumerable<T> foo) where T : class, IA
New contributor
I'm curious... what exactly is the reason behind the significance of the ordering?
– Tom Wright
yesterday
3
@TomWright - the spec doesn't, of course, include the answer to many "Why?" questions, but in this case does make it clear that there are three distinct types of constraints, and when all three are used they have to be specificallyprimary_constraint ',' secondary_constraints ',' constructor_constraint
– Damien_The_Unbeliever
yesterday
add a comment |
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
172
down vote
accepted
The error message is insufficiently informative, and that is my fault. Sorry about that.
The problem you are experiencing is a consequence of the fact that covariance only works on reference types.
Now, you're probably saying "but IA is a reference type" right now. Yes, it is. But you didn't say that T is IA. You said that T is a type which implements IA, and a value type can implement an interface.
If you want covariance to work you have to tell the compiler that the type parameter is a reference type with the class
constraint as well as the IA
interface constraint.
The error message really should say that the conversion is not possible because covariance requires a guarantee of reference-type-ness, since that is the fundamental problem.
2
Why you said it's your fault?
– user4951
2 days ago
56
@user4951: Because I implemented all of the conversion checking logic including the error messages.
– Eric Lippert
2 days ago
10
Admits fault and offers solution. IMO, +1 to Eric Lippert's personal rep.
– BurnsBA
2 days ago
1
@PeterA.Schneider: I appreciate that. But one of my primary goals for designing the error reporting logic in Roslyn was in particular to capture not just what rule was violated, but furthermore, to identify the "root cause" where possible. For example, what should the error message be forcustomers.Select(c=>c.FristName)
? The C# specification is very clear that this is an overload resolution error: the set of applicable methods named Select that can take that lambda is empty. But the root cause is thatFirstName
has a typo.
– Eric Lippert
yesterday
2
@PeterA.Schneider: I did a lot of work to ensure that scenarios involving generic type inference and lambdas used the appropriate heuristics to deduce what error message was likely to best help the developer. But I did a far less good job on the conversion error messages, particularly where variance was concerned. I've always regretted that.
– Eric Lippert
yesterday
|
show 1 more comment
up vote
172
down vote
accepted
The error message is insufficiently informative, and that is my fault. Sorry about that.
The problem you are experiencing is a consequence of the fact that covariance only works on reference types.
Now, you're probably saying "but IA is a reference type" right now. Yes, it is. But you didn't say that T is IA. You said that T is a type which implements IA, and a value type can implement an interface.
If you want covariance to work you have to tell the compiler that the type parameter is a reference type with the class
constraint as well as the IA
interface constraint.
The error message really should say that the conversion is not possible because covariance requires a guarantee of reference-type-ness, since that is the fundamental problem.
2
Why you said it's your fault?
– user4951
2 days ago
56
@user4951: Because I implemented all of the conversion checking logic including the error messages.
– Eric Lippert
2 days ago
10
Admits fault and offers solution. IMO, +1 to Eric Lippert's personal rep.
– BurnsBA
2 days ago
1
@PeterA.Schneider: I appreciate that. But one of my primary goals for designing the error reporting logic in Roslyn was in particular to capture not just what rule was violated, but furthermore, to identify the "root cause" where possible. For example, what should the error message be forcustomers.Select(c=>c.FristName)
? The C# specification is very clear that this is an overload resolution error: the set of applicable methods named Select that can take that lambda is empty. But the root cause is thatFirstName
has a typo.
– Eric Lippert
yesterday
2
@PeterA.Schneider: I did a lot of work to ensure that scenarios involving generic type inference and lambdas used the appropriate heuristics to deduce what error message was likely to best help the developer. But I did a far less good job on the conversion error messages, particularly where variance was concerned. I've always regretted that.
– Eric Lippert
yesterday
|
show 1 more comment
up vote
172
down vote
accepted
up vote
172
down vote
accepted
The error message is insufficiently informative, and that is my fault. Sorry about that.
The problem you are experiencing is a consequence of the fact that covariance only works on reference types.
Now, you're probably saying "but IA is a reference type" right now. Yes, it is. But you didn't say that T is IA. You said that T is a type which implements IA, and a value type can implement an interface.
If you want covariance to work you have to tell the compiler that the type parameter is a reference type with the class
constraint as well as the IA
interface constraint.
The error message really should say that the conversion is not possible because covariance requires a guarantee of reference-type-ness, since that is the fundamental problem.
The error message is insufficiently informative, and that is my fault. Sorry about that.
The problem you are experiencing is a consequence of the fact that covariance only works on reference types.
Now, you're probably saying "but IA is a reference type" right now. Yes, it is. But you didn't say that T is IA. You said that T is a type which implements IA, and a value type can implement an interface.
If you want covariance to work you have to tell the compiler that the type parameter is a reference type with the class
constraint as well as the IA
interface constraint.
The error message really should say that the conversion is not possible because covariance requires a guarantee of reference-type-ness, since that is the fundamental problem.
answered 2 days ago
Eric Lippert
527k14510391917
527k14510391917
2
Why you said it's your fault?
– user4951
2 days ago
56
@user4951: Because I implemented all of the conversion checking logic including the error messages.
– Eric Lippert
2 days ago
10
Admits fault and offers solution. IMO, +1 to Eric Lippert's personal rep.
– BurnsBA
2 days ago
1
@PeterA.Schneider: I appreciate that. But one of my primary goals for designing the error reporting logic in Roslyn was in particular to capture not just what rule was violated, but furthermore, to identify the "root cause" where possible. For example, what should the error message be forcustomers.Select(c=>c.FristName)
? The C# specification is very clear that this is an overload resolution error: the set of applicable methods named Select that can take that lambda is empty. But the root cause is thatFirstName
has a typo.
– Eric Lippert
yesterday
2
@PeterA.Schneider: I did a lot of work to ensure that scenarios involving generic type inference and lambdas used the appropriate heuristics to deduce what error message was likely to best help the developer. But I did a far less good job on the conversion error messages, particularly where variance was concerned. I've always regretted that.
– Eric Lippert
yesterday
|
show 1 more comment
2
Why you said it's your fault?
– user4951
2 days ago
56
@user4951: Because I implemented all of the conversion checking logic including the error messages.
– Eric Lippert
2 days ago
10
Admits fault and offers solution. IMO, +1 to Eric Lippert's personal rep.
– BurnsBA
2 days ago
1
@PeterA.Schneider: I appreciate that. But one of my primary goals for designing the error reporting logic in Roslyn was in particular to capture not just what rule was violated, but furthermore, to identify the "root cause" where possible. For example, what should the error message be forcustomers.Select(c=>c.FristName)
? The C# specification is very clear that this is an overload resolution error: the set of applicable methods named Select that can take that lambda is empty. But the root cause is thatFirstName
has a typo.
– Eric Lippert
yesterday
2
@PeterA.Schneider: I did a lot of work to ensure that scenarios involving generic type inference and lambdas used the appropriate heuristics to deduce what error message was likely to best help the developer. But I did a far less good job on the conversion error messages, particularly where variance was concerned. I've always regretted that.
– Eric Lippert
yesterday
2
2
Why you said it's your fault?
– user4951
2 days ago
Why you said it's your fault?
– user4951
2 days ago
56
56
@user4951: Because I implemented all of the conversion checking logic including the error messages.
– Eric Lippert
2 days ago
@user4951: Because I implemented all of the conversion checking logic including the error messages.
– Eric Lippert
2 days ago
10
10
Admits fault and offers solution. IMO, +1 to Eric Lippert's personal rep.
– BurnsBA
2 days ago
Admits fault and offers solution. IMO, +1 to Eric Lippert's personal rep.
– BurnsBA
2 days ago
1
1
@PeterA.Schneider: I appreciate that. But one of my primary goals for designing the error reporting logic in Roslyn was in particular to capture not just what rule was violated, but furthermore, to identify the "root cause" where possible. For example, what should the error message be for
customers.Select(c=>c.FristName)
? The C# specification is very clear that this is an overload resolution error: the set of applicable methods named Select that can take that lambda is empty. But the root cause is that FirstName
has a typo.– Eric Lippert
yesterday
@PeterA.Schneider: I appreciate that. But one of my primary goals for designing the error reporting logic in Roslyn was in particular to capture not just what rule was violated, but furthermore, to identify the "root cause" where possible. For example, what should the error message be for
customers.Select(c=>c.FristName)
? The C# specification is very clear that this is an overload resolution error: the set of applicable methods named Select that can take that lambda is empty. But the root cause is that FirstName
has a typo.– Eric Lippert
yesterday
2
2
@PeterA.Schneider: I did a lot of work to ensure that scenarios involving generic type inference and lambdas used the appropriate heuristics to deduce what error message was likely to best help the developer. But I did a far less good job on the conversion error messages, particularly where variance was concerned. I've always regretted that.
– Eric Lippert
yesterday
@PeterA.Schneider: I did a lot of work to ensure that scenarios involving generic type inference and lambdas used the appropriate heuristics to deduce what error message was likely to best help the developer. But I did a far less good job on the conversion error messages, particularly where variance was concerned. I've always regretted that.
– Eric Lippert
yesterday
|
show 1 more comment
up vote
14
down vote
I just wanted to complement Eric's excellent insider answer with a code example for those that may not be that familiar with generic constraints.
Change Something
's signature like this: The class
constraint has to come first.
public static IList<T> Something<T>(IEnumerable<T> foo) where T : class, IA
New contributor
I'm curious... what exactly is the reason behind the significance of the ordering?
– Tom Wright
yesterday
3
@TomWright - the spec doesn't, of course, include the answer to many "Why?" questions, but in this case does make it clear that there are three distinct types of constraints, and when all three are used they have to be specificallyprimary_constraint ',' secondary_constraints ',' constructor_constraint
– Damien_The_Unbeliever
yesterday
add a comment |
up vote
14
down vote
I just wanted to complement Eric's excellent insider answer with a code example for those that may not be that familiar with generic constraints.
Change Something
's signature like this: The class
constraint has to come first.
public static IList<T> Something<T>(IEnumerable<T> foo) where T : class, IA
New contributor
I'm curious... what exactly is the reason behind the significance of the ordering?
– Tom Wright
yesterday
3
@TomWright - the spec doesn't, of course, include the answer to many "Why?" questions, but in this case does make it clear that there are three distinct types of constraints, and when all three are used they have to be specificallyprimary_constraint ',' secondary_constraints ',' constructor_constraint
– Damien_The_Unbeliever
yesterday
add a comment |
up vote
14
down vote
up vote
14
down vote
I just wanted to complement Eric's excellent insider answer with a code example for those that may not be that familiar with generic constraints.
Change Something
's signature like this: The class
constraint has to come first.
public static IList<T> Something<T>(IEnumerable<T> foo) where T : class, IA
New contributor
I just wanted to complement Eric's excellent insider answer with a code example for those that may not be that familiar with generic constraints.
Change Something
's signature like this: The class
constraint has to come first.
public static IList<T> Something<T>(IEnumerable<T> foo) where T : class, IA
New contributor
edited 2 days ago
Peter Mortensen
13.2k1983111
13.2k1983111
New contributor
answered 2 days ago
Marcell Tóth
40410
40410
New contributor
New contributor
I'm curious... what exactly is the reason behind the significance of the ordering?
– Tom Wright
yesterday
3
@TomWright - the spec doesn't, of course, include the answer to many "Why?" questions, but in this case does make it clear that there are three distinct types of constraints, and when all three are used they have to be specificallyprimary_constraint ',' secondary_constraints ',' constructor_constraint
– Damien_The_Unbeliever
yesterday
add a comment |
I'm curious... what exactly is the reason behind the significance of the ordering?
– Tom Wright
yesterday
3
@TomWright - the spec doesn't, of course, include the answer to many "Why?" questions, but in this case does make it clear that there are three distinct types of constraints, and when all three are used they have to be specificallyprimary_constraint ',' secondary_constraints ',' constructor_constraint
– Damien_The_Unbeliever
yesterday
I'm curious... what exactly is the reason behind the significance of the ordering?
– Tom Wright
yesterday
I'm curious... what exactly is the reason behind the significance of the ordering?
– Tom Wright
yesterday
3
3
@TomWright - the spec doesn't, of course, include the answer to many "Why?" questions, but in this case does make it clear that there are three distinct types of constraints, and when all three are used they have to be specifically
primary_constraint ',' secondary_constraints ',' constructor_constraint
– Damien_The_Unbeliever
yesterday
@TomWright - the spec doesn't, of course, include the answer to many "Why?" questions, but in this case does make it clear that there are three distinct types of constraints, and when all three are used they have to be specifically
primary_constraint ',' secondary_constraints ',' constructor_constraint
– Damien_The_Unbeliever
yesterday
add a comment |
BenLaz is a new contributor. Be nice, and check out our Code of Conduct.
BenLaz is a new contributor. Be nice, and check out our Code of Conduct.
BenLaz is a new contributor. Be nice, and check out our Code of Conduct.
BenLaz is a new contributor. Be nice, and check out our Code of Conduct.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53185806%2fproblem-understanding-covariance-contravariance-with-generics-in-c-sharp%23new-answer', 'question_page');
}
);
Post as a guest
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
7
Possible duplicate of Why covariance and contravariance do not support value type
– Dirk
2 days ago
9
You have not restricted
T
to reference types. If you use the conditionwhere T: class, IA
then it should work. The linked answer has more details.– Dirk
2 days ago
1
@Dirk I don't think this should be flagged as a duplicate. While it's true that the concept problem here is a covariance/contravariance problem in the face of value types, the specific case here is "what does this error message mean" as well as the author not realizing merely including "class" fixes his issue. I believe future users will search for this error message, find this post, and leave happy. (As I often do.)
– Reginald Blue
2 days ago
You can also reproduce the situation by simply saying
Something2(foo);
directly. Going around.ToList()
to get aList<T>
(T
is your type parameter declared by the generic method) is not needed to understand this (aList<T>
is anIEnumerable<T>
).– Jeppe Stig Nielsen
yesterday