Problem understanding covariance contravariance with generics in C#
Clash Royale CLAN TAG#URR8PPP
up vote
6
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>
.
Can someone explain it to me (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
BenLaz is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.
add a comment |Â
up vote
6
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>
.
Can someone explain it to me (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
BenLaz is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.
2
Possible duplicate of Why covariance and contravariance do not support value type
– Dirk
20 mins ago
2
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
19 mins ago
1
@SeM: Please do not use the comment system to complain; use comments to request clarification of the question.
– Eric Lippert
9 mins ago
add a comment |Â
up vote
6
down vote
favorite
up vote
6
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>
.
Can someone explain it to me (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
BenLaz is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.
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>
.
Can someone explain it to me (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
BenLaz is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.
New contributor
BenLaz is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.
edited 19 mins ago
Luiso
2,18921844
2,18921844
New contributor
BenLaz is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.
asked 30 mins ago
BenLaz
1343
1343
New contributor
BenLaz is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.
New contributor
BenLaz is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.
BenLaz is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.
2
Possible duplicate of Why covariance and contravariance do not support value type
– Dirk
20 mins ago
2
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
19 mins ago
1
@SeM: Please do not use the comment system to complain; use comments to request clarification of the question.
– Eric Lippert
9 mins ago
add a comment |Â
2
Possible duplicate of Why covariance and contravariance do not support value type
– Dirk
20 mins ago
2
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
19 mins ago
1
@SeM: Please do not use the comment system to complain; use comments to request clarification of the question.
– Eric Lippert
9 mins ago
2
2
Possible duplicate of Why covariance and contravariance do not support value type
– Dirk
20 mins ago
Possible duplicate of Why covariance and contravariance do not support value type
– Dirk
20 mins ago
2
2
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
19 mins 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
19 mins ago
1
1
@SeM: Please do not use the comment system to complain; use comments to request clarification of the question.
– Eric Lippert
9 mins ago
@SeM: Please do not use the comment system to complain; use comments to request clarification of the question.
– Eric Lippert
9 mins ago
add a comment |Â
1 Answer
1
active
oldest
votes
up vote
13
down vote
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.
add a comment |Â
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
13
down vote
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.
add a comment |Â
up vote
13
down vote
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.
add a comment |Â
up vote
13
down vote
up vote
13
down vote
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 19 mins ago
Eric Lippert
527k14310361917
527k14310361917
add a comment |Â
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
2
Possible duplicate of Why covariance and contravariance do not support value type
– Dirk
20 mins ago
2
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
19 mins ago
1
@SeM: Please do not use the comment system to complain; use comments to request clarification of the question.
– Eric Lippert
9 mins ago