Problem understanding covariance contravariance with generics in C#











up vote
74
down vote

favorite
10












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









share|improve this question









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.
















  • 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 condition where 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 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















up vote
74
down vote

favorite
10












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









share|improve this question









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.
















  • 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 condition where 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 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













up vote
74
down vote

favorite
10









up vote
74
down vote

favorite
10






10





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









share|improve this question









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



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






share|improve this question









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.











share|improve this question









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.









share|improve this question




share|improve this question








edited 2 days ago









Peter Mortensen

13.2k1983111




13.2k1983111






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 2 days ago









BenLaz

44847




44847




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.








  • 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 condition where 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 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














  • 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 condition where 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 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








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












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.






share|improve this answer

















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




    @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


















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





share|improve this answer










New contributor




Marcell Tóth is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.


















  • 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 specifically primary_constraint ',' secondary_constraints ',' constructor_constraint
    – Damien_The_Unbeliever
    yesterday











Your Answer






StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");

StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});

function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});


}
});






BenLaz is a new contributor. Be nice, and check out our Code of Conduct.










 

draft saved


draft discarded


















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
































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.






share|improve this answer

















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




    @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















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.






share|improve this answer

















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




    @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













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.






share|improve this answer












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.







share|improve this answer












share|improve this answer



share|improve this answer










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




    @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




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




    @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












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





share|improve this answer










New contributor




Marcell Tóth is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.


















  • 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 specifically primary_constraint ',' secondary_constraints ',' constructor_constraint
    – Damien_The_Unbeliever
    yesterday















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





share|improve this answer










New contributor




Marcell Tóth is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.


















  • 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 specifically primary_constraint ',' secondary_constraints ',' constructor_constraint
    – Damien_The_Unbeliever
    yesterday













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





share|improve this answer










New contributor




Marcell Tóth is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.









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






share|improve this answer










New contributor




Marcell Tóth is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.









share|improve this answer



share|improve this answer








edited 2 days ago









Peter Mortensen

13.2k1983111




13.2k1983111






New contributor




Marcell Tóth is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.









answered 2 days ago









Marcell Tóth

40410




40410




New contributor




Marcell Tóth is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.





New contributor





Marcell Tóth is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.






Marcell Tóth is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.












  • 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 specifically primary_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






  • 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
















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










BenLaz is a new contributor. Be nice, and check out our Code of Conduct.










 

draft saved


draft discarded


















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.















 


draft saved


draft discarded














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




















































































Popular posts from this blog

Schultheiß

Verwaltungsgliederung Dänemarks

Liste der Kulturdenkmale in Wilsdruff