How can I add a type invariant setter to a covariant interface?











up vote
6
down vote

favorite
2












I have a type Shelter that needs to be covariant, so that an override in another class* can return a Shelter<Cat> where a Shelter<Animal> is expected. Since classes cannot be co- or contravariant in C#, I added an interface:



public interface IShelter<out AnimalType>
{
AnimalType Contents { get; }
}


However, there is a place where an IShelter (compile-time type) is assigned a new animal, where we know for sure that the animal being set is going to be a Cat. At first, I thought I could just add a set to the Contents property and do:



IShelter<Cat> shelter = new Shelter(new Cat());
shelter.Contents = new Cat();


But adding the setter is not possible;



Error   CS1961  Invalid variance: The type parameter 'AnimalType' must be invariantly valid on 'IShelter<AnimalType>.Contents'. 'AnimalType' is covariant.


This makes sense, because otherwise I could pass the catshelter to this function:



private static void UseShelter(IShelter<Animal> s)
{
s.Contents = new Lion();
}


However, I'm not going to do that. It would be nice to have some way to mark the setter as invariant so that the UseShelter function would only be able to assign an Animal, and so that this would be enforced at compile-time. The reason I need this is because there is a place in my code that knows it has a Shelter<Cat>, and needs to re-assign the Contents property to a new Cat.



The workaround I found so far is to add a jucky runtime type check in an explicit set function; Juck!



public void SetContents(object newContents)
{
if (newContents.GetType() != typeof(AnimalType))
{
throw new InvalidOperationException("SetContents must be given the correct AnimalType");
}
Contents = (AnimalType)newContents;
}


The parameter needs to be of type object, so that this function can be specified in the interface. Is there any way to enforce this at compile-time?



* To clarify, there is a function: public virtual IShelter<Animal> GetAnimalShelter() that is overridden and returns an IShelter<Cat>:



public override IShelter<Animal> GetAnimalShelter(){
IShelter<Cat> = new Shelter<Cat>(new Cat());
}


A minimal working example including most of the code above follows:



class Animal { }
class Cat : Animal { }
class Lion : Animal { }

public interface IShelter<out AnimalType>
{
AnimalType Contents { get; }

void SetContents(object newContents);
}

class Shelter<AnimalType> : IShelter<AnimalType>
{
public Shelter(AnimalType animal)
{
}

public void SetContents(object newContents)
{
if (newContents.GetType() != typeof(AnimalType))
{
throw new InvalidOperationException("SetContents must be given the correct AnimalType");
}
Contents = (AnimalType)newContents;
}

public AnimalType Contents { get; set; }
}

class Usage
{
public static void Main()
{
IShelter<Cat> catshelter = new Shelter<Cat>(new Cat());
catshelter.SetContents(new Cat());
catshelter.SetContents(new Lion()); // should be disallowed by the compiler
}
}









share|improve this question
























  • I might be missing something obvious here, but shouldn't a simple {get; set;} do the trick here? I mean, the type of the property is Cat...
    – Zohar Peled
    Nov 8 at 9:18






  • 1




    @marsze look at it now... as it wasnt wrapped in code ticks the angle braces were ignored
    – Jamiec
    Nov 8 at 9:23








  • 1




    How about sealing Cat?
    – Lasse Vågsæther Karlsen
    Nov 8 at 11:39






  • 1




    @marsze I added an explanation of the required override; any other usage of covariance for the interface would do just as well, but that is mine as it is.
    – TamaMcGlinn
    Nov 8 at 11:39






  • 1




    The problem here is that without restructuring the rest of C# as well, you would incur the runtime cost of checking either way. Let's say the interface allowed you to say "Only Cat, nothing else", what if I first do Cat c = new Lion(); ?
    – Lasse Vågsæther Karlsen
    Nov 8 at 11:40















up vote
6
down vote

favorite
2












I have a type Shelter that needs to be covariant, so that an override in another class* can return a Shelter<Cat> where a Shelter<Animal> is expected. Since classes cannot be co- or contravariant in C#, I added an interface:



public interface IShelter<out AnimalType>
{
AnimalType Contents { get; }
}


However, there is a place where an IShelter (compile-time type) is assigned a new animal, where we know for sure that the animal being set is going to be a Cat. At first, I thought I could just add a set to the Contents property and do:



IShelter<Cat> shelter = new Shelter(new Cat());
shelter.Contents = new Cat();


But adding the setter is not possible;



Error   CS1961  Invalid variance: The type parameter 'AnimalType' must be invariantly valid on 'IShelter<AnimalType>.Contents'. 'AnimalType' is covariant.


This makes sense, because otherwise I could pass the catshelter to this function:



private static void UseShelter(IShelter<Animal> s)
{
s.Contents = new Lion();
}


However, I'm not going to do that. It would be nice to have some way to mark the setter as invariant so that the UseShelter function would only be able to assign an Animal, and so that this would be enforced at compile-time. The reason I need this is because there is a place in my code that knows it has a Shelter<Cat>, and needs to re-assign the Contents property to a new Cat.



The workaround I found so far is to add a jucky runtime type check in an explicit set function; Juck!



public void SetContents(object newContents)
{
if (newContents.GetType() != typeof(AnimalType))
{
throw new InvalidOperationException("SetContents must be given the correct AnimalType");
}
Contents = (AnimalType)newContents;
}


The parameter needs to be of type object, so that this function can be specified in the interface. Is there any way to enforce this at compile-time?



* To clarify, there is a function: public virtual IShelter<Animal> GetAnimalShelter() that is overridden and returns an IShelter<Cat>:



public override IShelter<Animal> GetAnimalShelter(){
IShelter<Cat> = new Shelter<Cat>(new Cat());
}


A minimal working example including most of the code above follows:



class Animal { }
class Cat : Animal { }
class Lion : Animal { }

public interface IShelter<out AnimalType>
{
AnimalType Contents { get; }

void SetContents(object newContents);
}

class Shelter<AnimalType> : IShelter<AnimalType>
{
public Shelter(AnimalType animal)
{
}

public void SetContents(object newContents)
{
if (newContents.GetType() != typeof(AnimalType))
{
throw new InvalidOperationException("SetContents must be given the correct AnimalType");
}
Contents = (AnimalType)newContents;
}

public AnimalType Contents { get; set; }
}

class Usage
{
public static void Main()
{
IShelter<Cat> catshelter = new Shelter<Cat>(new Cat());
catshelter.SetContents(new Cat());
catshelter.SetContents(new Lion()); // should be disallowed by the compiler
}
}









share|improve this question
























  • I might be missing something obvious here, but shouldn't a simple {get; set;} do the trick here? I mean, the type of the property is Cat...
    – Zohar Peled
    Nov 8 at 9:18






  • 1




    @marsze look at it now... as it wasnt wrapped in code ticks the angle braces were ignored
    – Jamiec
    Nov 8 at 9:23








  • 1




    How about sealing Cat?
    – Lasse Vågsæther Karlsen
    Nov 8 at 11:39






  • 1




    @marsze I added an explanation of the required override; any other usage of covariance for the interface would do just as well, but that is mine as it is.
    – TamaMcGlinn
    Nov 8 at 11:39






  • 1




    The problem here is that without restructuring the rest of C# as well, you would incur the runtime cost of checking either way. Let's say the interface allowed you to say "Only Cat, nothing else", what if I first do Cat c = new Lion(); ?
    – Lasse Vågsæther Karlsen
    Nov 8 at 11:40













up vote
6
down vote

favorite
2









up vote
6
down vote

favorite
2






2





I have a type Shelter that needs to be covariant, so that an override in another class* can return a Shelter<Cat> where a Shelter<Animal> is expected. Since classes cannot be co- or contravariant in C#, I added an interface:



public interface IShelter<out AnimalType>
{
AnimalType Contents { get; }
}


However, there is a place where an IShelter (compile-time type) is assigned a new animal, where we know for sure that the animal being set is going to be a Cat. At first, I thought I could just add a set to the Contents property and do:



IShelter<Cat> shelter = new Shelter(new Cat());
shelter.Contents = new Cat();


But adding the setter is not possible;



Error   CS1961  Invalid variance: The type parameter 'AnimalType' must be invariantly valid on 'IShelter<AnimalType>.Contents'. 'AnimalType' is covariant.


This makes sense, because otherwise I could pass the catshelter to this function:



private static void UseShelter(IShelter<Animal> s)
{
s.Contents = new Lion();
}


However, I'm not going to do that. It would be nice to have some way to mark the setter as invariant so that the UseShelter function would only be able to assign an Animal, and so that this would be enforced at compile-time. The reason I need this is because there is a place in my code that knows it has a Shelter<Cat>, and needs to re-assign the Contents property to a new Cat.



The workaround I found so far is to add a jucky runtime type check in an explicit set function; Juck!



public void SetContents(object newContents)
{
if (newContents.GetType() != typeof(AnimalType))
{
throw new InvalidOperationException("SetContents must be given the correct AnimalType");
}
Contents = (AnimalType)newContents;
}


The parameter needs to be of type object, so that this function can be specified in the interface. Is there any way to enforce this at compile-time?



* To clarify, there is a function: public virtual IShelter<Animal> GetAnimalShelter() that is overridden and returns an IShelter<Cat>:



public override IShelter<Animal> GetAnimalShelter(){
IShelter<Cat> = new Shelter<Cat>(new Cat());
}


A minimal working example including most of the code above follows:



class Animal { }
class Cat : Animal { }
class Lion : Animal { }

public interface IShelter<out AnimalType>
{
AnimalType Contents { get; }

void SetContents(object newContents);
}

class Shelter<AnimalType> : IShelter<AnimalType>
{
public Shelter(AnimalType animal)
{
}

public void SetContents(object newContents)
{
if (newContents.GetType() != typeof(AnimalType))
{
throw new InvalidOperationException("SetContents must be given the correct AnimalType");
}
Contents = (AnimalType)newContents;
}

public AnimalType Contents { get; set; }
}

class Usage
{
public static void Main()
{
IShelter<Cat> catshelter = new Shelter<Cat>(new Cat());
catshelter.SetContents(new Cat());
catshelter.SetContents(new Lion()); // should be disallowed by the compiler
}
}









share|improve this question















I have a type Shelter that needs to be covariant, so that an override in another class* can return a Shelter<Cat> where a Shelter<Animal> is expected. Since classes cannot be co- or contravariant in C#, I added an interface:



public interface IShelter<out AnimalType>
{
AnimalType Contents { get; }
}


However, there is a place where an IShelter (compile-time type) is assigned a new animal, where we know for sure that the animal being set is going to be a Cat. At first, I thought I could just add a set to the Contents property and do:



IShelter<Cat> shelter = new Shelter(new Cat());
shelter.Contents = new Cat();


But adding the setter is not possible;



Error   CS1961  Invalid variance: The type parameter 'AnimalType' must be invariantly valid on 'IShelter<AnimalType>.Contents'. 'AnimalType' is covariant.


This makes sense, because otherwise I could pass the catshelter to this function:



private static void UseShelter(IShelter<Animal> s)
{
s.Contents = new Lion();
}


However, I'm not going to do that. It would be nice to have some way to mark the setter as invariant so that the UseShelter function would only be able to assign an Animal, and so that this would be enforced at compile-time. The reason I need this is because there is a place in my code that knows it has a Shelter<Cat>, and needs to re-assign the Contents property to a new Cat.



The workaround I found so far is to add a jucky runtime type check in an explicit set function; Juck!



public void SetContents(object newContents)
{
if (newContents.GetType() != typeof(AnimalType))
{
throw new InvalidOperationException("SetContents must be given the correct AnimalType");
}
Contents = (AnimalType)newContents;
}


The parameter needs to be of type object, so that this function can be specified in the interface. Is there any way to enforce this at compile-time?



* To clarify, there is a function: public virtual IShelter<Animal> GetAnimalShelter() that is overridden and returns an IShelter<Cat>:



public override IShelter<Animal> GetAnimalShelter(){
IShelter<Cat> = new Shelter<Cat>(new Cat());
}


A minimal working example including most of the code above follows:



class Animal { }
class Cat : Animal { }
class Lion : Animal { }

public interface IShelter<out AnimalType>
{
AnimalType Contents { get; }

void SetContents(object newContents);
}

class Shelter<AnimalType> : IShelter<AnimalType>
{
public Shelter(AnimalType animal)
{
}

public void SetContents(object newContents)
{
if (newContents.GetType() != typeof(AnimalType))
{
throw new InvalidOperationException("SetContents must be given the correct AnimalType");
}
Contents = (AnimalType)newContents;
}

public AnimalType Contents { get; set; }
}

class Usage
{
public static void Main()
{
IShelter<Cat> catshelter = new Shelter<Cat>(new Cat());
catshelter.SetContents(new Cat());
catshelter.SetContents(new Lion()); // should be disallowed by the compiler
}
}






c# covariance






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 8 at 11:37

























asked Nov 8 at 9:09









TamaMcGlinn

430315




430315












  • I might be missing something obvious here, but shouldn't a simple {get; set;} do the trick here? I mean, the type of the property is Cat...
    – Zohar Peled
    Nov 8 at 9:18






  • 1




    @marsze look at it now... as it wasnt wrapped in code ticks the angle braces were ignored
    – Jamiec
    Nov 8 at 9:23








  • 1




    How about sealing Cat?
    – Lasse Vågsæther Karlsen
    Nov 8 at 11:39






  • 1




    @marsze I added an explanation of the required override; any other usage of covariance for the interface would do just as well, but that is mine as it is.
    – TamaMcGlinn
    Nov 8 at 11:39






  • 1




    The problem here is that without restructuring the rest of C# as well, you would incur the runtime cost of checking either way. Let's say the interface allowed you to say "Only Cat, nothing else", what if I first do Cat c = new Lion(); ?
    – Lasse Vågsæther Karlsen
    Nov 8 at 11:40


















  • I might be missing something obvious here, but shouldn't a simple {get; set;} do the trick here? I mean, the type of the property is Cat...
    – Zohar Peled
    Nov 8 at 9:18






  • 1




    @marsze look at it now... as it wasnt wrapped in code ticks the angle braces were ignored
    – Jamiec
    Nov 8 at 9:23








  • 1




    How about sealing Cat?
    – Lasse Vågsæther Karlsen
    Nov 8 at 11:39






  • 1




    @marsze I added an explanation of the required override; any other usage of covariance for the interface would do just as well, but that is mine as it is.
    – TamaMcGlinn
    Nov 8 at 11:39






  • 1




    The problem here is that without restructuring the rest of C# as well, you would incur the runtime cost of checking either way. Let's say the interface allowed you to say "Only Cat, nothing else", what if I first do Cat c = new Lion(); ?
    – Lasse Vågsæther Karlsen
    Nov 8 at 11:40
















I might be missing something obvious here, but shouldn't a simple {get; set;} do the trick here? I mean, the type of the property is Cat...
– Zohar Peled
Nov 8 at 9:18




I might be missing something obvious here, but shouldn't a simple {get; set;} do the trick here? I mean, the type of the property is Cat...
– Zohar Peled
Nov 8 at 9:18




1




1




@marsze look at it now... as it wasnt wrapped in code ticks the angle braces were ignored
– Jamiec
Nov 8 at 9:23






@marsze look at it now... as it wasnt wrapped in code ticks the angle braces were ignored
– Jamiec
Nov 8 at 9:23






1




1




How about sealing Cat?
– Lasse Vågsæther Karlsen
Nov 8 at 11:39




How about sealing Cat?
– Lasse Vågsæther Karlsen
Nov 8 at 11:39




1




1




@marsze I added an explanation of the required override; any other usage of covariance for the interface would do just as well, but that is mine as it is.
– TamaMcGlinn
Nov 8 at 11:39




@marsze I added an explanation of the required override; any other usage of covariance for the interface would do just as well, but that is mine as it is.
– TamaMcGlinn
Nov 8 at 11:39




1




1




The problem here is that without restructuring the rest of C# as well, you would incur the runtime cost of checking either way. Let's say the interface allowed you to say "Only Cat, nothing else", what if I first do Cat c = new Lion(); ?
– Lasse Vågsæther Karlsen
Nov 8 at 11:40




The problem here is that without restructuring the rest of C# as well, you would incur the runtime cost of checking either way. Let's say the interface allowed you to say "Only Cat, nothing else", what if I first do Cat c = new Lion(); ?
– Lasse Vågsæther Karlsen
Nov 8 at 11:40












3 Answers
3






active

oldest

votes

















up vote
2
down vote



accepted










In a case like this, just remove the setter from the interface and use the concrete type (or infer it using var as in this example). After all, if the code "knows" for sure it is adding a cat, it probably also knows the shelter's concrete type.



interface IShelter<out AnimalType>
{
AnimalType Contents { get; }
}

class Shelter<AnimalType> : IShelter<AnimalType>
{
public Shelter(AnimalType animal)
{
}

public void SetContents(AnimalType newContents)
{
Contents = newContents;
}

public AnimalType Contents { get; set; }
}

public class Usage
{
public static void Main()
{
var catshelter = new Shelter<Cat>(new Cat());
catshelter.SetContents(new Cat());
catshelter.SetContents(new Lion()); // Is disallowed by the compiler
}
}


Example on DotNetFiddle



The same pattern is followed by many CLR classes under System.Collections.Generic. Lots of classes implement IEnumerable<T>, which is covariant; but if you want to call the methods that allow you to add, you have to reference it as a concrete class such as List<T>. Or if you really want to add via an interface you could use IList<T>. But in no case is there a single covariant interface that also allows you to add.






share|improve this answer























  • Neat. It still bothers me though to have a property with only a getter and an extra method for setting it. One could skip the setter altogether, as the animal is provided with the constructor (which would make it immutable), or also provide a GetContents method to make it more symmetric. Just a personal opinion.
    – marsze
    Nov 8 at 11:52






  • 1




    I would change a lot of things (TAnimal instead of AnimalType for one) but the code is based on the OP's original example, modified only to demonstrate the principle.
    – John Wu
    Nov 8 at 12:08










  • Yeah my comment was primarily meant for OP rather than you. Great answer, esp. the explanations about how it's solved in the framework.
    – marsze
    Nov 8 at 12:12










  • Indeed, I prefer using a setter as well. The seperate function was just so that it can accept object and cast it, as I had thought was necessary. Also, it was really helpful to point out that List<T> already does this with respect to IEnumerable<T>. I use those classes every day but somehow missed that fact.
    – TamaMcGlinn
    Nov 8 at 19:55


















up vote
0
down vote













The only solution I could think of so far would be using 2 separate interfaces for each of your concerns (IShelter and ISpecificShelter):



// this replaces IShelter<Animal>
public interface IShelter
{
Animal Animal { get; set; }
}

// this replaces IShelter<SpecificAnimal>
public interface ISpecificShelter<AnimalType> : IShelter where AnimalType : Animal
{
new AnimalType Animal { get; set; }
}

// implementation
public class Shelter<AnimalType> : ISpecificShelter<AnimalType> where AnimalType : Animal
{
private Animal _animal;

// explicit implementation, so the correct implementation is called depending on what interface is used
Animal IShelter.Animal { get { return _animal; } set { _animal = value; } }
AnimalType ISpecificShelter<AnimalType>.Animal { get { return (AnimalType)_animal; } set { _animal = value; } }

public Shelter()
{ }
}


Usage:



// specific animal
ISpecificShelter<Cat> catShelter = new Shelter<Cat>();
catShelter.Animal = new Cat();
catShelter.Animal = new Lion(); // => compiler error!
Cat cat = catShelter.Animal;

// cast to general interface
IShelter shelter = catShelter;
Animal animal = shelter.Animal;


If you want to prevent instancing the class directly, but only work with the interfaces, you could implement a factory pattern:



public static class Shelter
{
public static IShelter Create()
{
return new Implementation<Animal>();
}

public static IShelter Create(Animal animal)
{
return new Implementation<Animal>(animal);
}

public static ISpecificShelter<AnimalType> Create<AnimalType>() where AnimalType : Animal
{
return new Implementation<AnimalType>();
}

public static ISpecificShelter<AnimalType> Create<AnimalType>(AnimalType animal) where AnimalType : Animal
{
return new Implementation<AnimalType>(animal);
}

private class Implementation<AnimalType> : ISpecificShelter<AnimalType> where AnimalType : Animal
{
private Animal _animal;

Animal IShelter.Animal { get { return _animal; } set { _animal = value; } }
AnimalType ISpecificShelter<AnimalType>.Animal { get { return (AnimalType)_animal; } set { _animal = value; } }

public Implementation()
{ }

public Implementation(AnimalType animal)
{
_animal = animal;
}
}
}


Usage:



var shelter = Shelter.Create();
shelter.Animal = new Lion();
// OR:
// var shelter = Shelter.Create(new Lion());
var animal = shelter.Animal;

var catShelter = Shelter.Create<Cat>();
catShelter.Animal = new Cat();
// OR:
// var catShelter = Shelter.Create(new Cat());
var cat = catShelter.Animal;

// cast is also possible:
shelter = (IShelter)catShelter;


It really depends on your specific use cases. You should provide more examples and information on what exactly you want to do and why.






share|improve this answer























  • Essentially your answer is the same as John Wu's; it's just that his is more succinct because he leaves out the ISpecificShelter and refers directly to Shelter. It's a shame you got downvoted despite being the first to post a correct solution.
    – TamaMcGlinn
    Nov 8 at 19:58










  • @TamaMcGlinn I would have liked to know why. I am always open for positive critcism and suggestions to improve. I really like @JohnWu`s answer best, but I think my design isn't so bad either.
    – marsze
    Nov 8 at 20:05


















up vote
0
down vote













What you are trying to achieve is not possible, because technically you want to have interface which is both covariant and contravariant. Limitations of each type of variance are well explained here in this SO answer



So, if you want to be able to set more derived type (e.g TDerived : T) to the Contents property, you should use contravariant interface:



public interface IShelter<in T>
{
T Contents { set; }
}


On the other hand, if you want to be able to pass Contents to less derived type (e.g. T : TBase), you should stick with your current implementation:



public interface IShelter<out T>
{
T Contents { get; }
}


Any other combination would result in possible runtime errors, that's why the compiler doesn't allow you to have an interface which is both co- and contravariant.



So, either use two distinct interfaces to achieve what you want, or rethink/polish your architecture around these types.






share|improve this answer























    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
    });


    }
    });














     

    draft saved


    draft discarded


















    StackExchange.ready(
    function () {
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53204536%2fhow-can-i-add-a-type-invariant-setter-to-a-covariant-interface%23new-answer', 'question_page');
    }
    );

    Post as a guest
































    3 Answers
    3






    active

    oldest

    votes








    3 Answers
    3






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes








    up vote
    2
    down vote



    accepted










    In a case like this, just remove the setter from the interface and use the concrete type (or infer it using var as in this example). After all, if the code "knows" for sure it is adding a cat, it probably also knows the shelter's concrete type.



    interface IShelter<out AnimalType>
    {
    AnimalType Contents { get; }
    }

    class Shelter<AnimalType> : IShelter<AnimalType>
    {
    public Shelter(AnimalType animal)
    {
    }

    public void SetContents(AnimalType newContents)
    {
    Contents = newContents;
    }

    public AnimalType Contents { get; set; }
    }

    public class Usage
    {
    public static void Main()
    {
    var catshelter = new Shelter<Cat>(new Cat());
    catshelter.SetContents(new Cat());
    catshelter.SetContents(new Lion()); // Is disallowed by the compiler
    }
    }


    Example on DotNetFiddle



    The same pattern is followed by many CLR classes under System.Collections.Generic. Lots of classes implement IEnumerable<T>, which is covariant; but if you want to call the methods that allow you to add, you have to reference it as a concrete class such as List<T>. Or if you really want to add via an interface you could use IList<T>. But in no case is there a single covariant interface that also allows you to add.






    share|improve this answer























    • Neat. It still bothers me though to have a property with only a getter and an extra method for setting it. One could skip the setter altogether, as the animal is provided with the constructor (which would make it immutable), or also provide a GetContents method to make it more symmetric. Just a personal opinion.
      – marsze
      Nov 8 at 11:52






    • 1




      I would change a lot of things (TAnimal instead of AnimalType for one) but the code is based on the OP's original example, modified only to demonstrate the principle.
      – John Wu
      Nov 8 at 12:08










    • Yeah my comment was primarily meant for OP rather than you. Great answer, esp. the explanations about how it's solved in the framework.
      – marsze
      Nov 8 at 12:12










    • Indeed, I prefer using a setter as well. The seperate function was just so that it can accept object and cast it, as I had thought was necessary. Also, it was really helpful to point out that List<T> already does this with respect to IEnumerable<T>. I use those classes every day but somehow missed that fact.
      – TamaMcGlinn
      Nov 8 at 19:55















    up vote
    2
    down vote



    accepted










    In a case like this, just remove the setter from the interface and use the concrete type (or infer it using var as in this example). After all, if the code "knows" for sure it is adding a cat, it probably also knows the shelter's concrete type.



    interface IShelter<out AnimalType>
    {
    AnimalType Contents { get; }
    }

    class Shelter<AnimalType> : IShelter<AnimalType>
    {
    public Shelter(AnimalType animal)
    {
    }

    public void SetContents(AnimalType newContents)
    {
    Contents = newContents;
    }

    public AnimalType Contents { get; set; }
    }

    public class Usage
    {
    public static void Main()
    {
    var catshelter = new Shelter<Cat>(new Cat());
    catshelter.SetContents(new Cat());
    catshelter.SetContents(new Lion()); // Is disallowed by the compiler
    }
    }


    Example on DotNetFiddle



    The same pattern is followed by many CLR classes under System.Collections.Generic. Lots of classes implement IEnumerable<T>, which is covariant; but if you want to call the methods that allow you to add, you have to reference it as a concrete class such as List<T>. Or if you really want to add via an interface you could use IList<T>. But in no case is there a single covariant interface that also allows you to add.






    share|improve this answer























    • Neat. It still bothers me though to have a property with only a getter and an extra method for setting it. One could skip the setter altogether, as the animal is provided with the constructor (which would make it immutable), or also provide a GetContents method to make it more symmetric. Just a personal opinion.
      – marsze
      Nov 8 at 11:52






    • 1




      I would change a lot of things (TAnimal instead of AnimalType for one) but the code is based on the OP's original example, modified only to demonstrate the principle.
      – John Wu
      Nov 8 at 12:08










    • Yeah my comment was primarily meant for OP rather than you. Great answer, esp. the explanations about how it's solved in the framework.
      – marsze
      Nov 8 at 12:12










    • Indeed, I prefer using a setter as well. The seperate function was just so that it can accept object and cast it, as I had thought was necessary. Also, it was really helpful to point out that List<T> already does this with respect to IEnumerable<T>. I use those classes every day but somehow missed that fact.
      – TamaMcGlinn
      Nov 8 at 19:55













    up vote
    2
    down vote



    accepted







    up vote
    2
    down vote



    accepted






    In a case like this, just remove the setter from the interface and use the concrete type (or infer it using var as in this example). After all, if the code "knows" for sure it is adding a cat, it probably also knows the shelter's concrete type.



    interface IShelter<out AnimalType>
    {
    AnimalType Contents { get; }
    }

    class Shelter<AnimalType> : IShelter<AnimalType>
    {
    public Shelter(AnimalType animal)
    {
    }

    public void SetContents(AnimalType newContents)
    {
    Contents = newContents;
    }

    public AnimalType Contents { get; set; }
    }

    public class Usage
    {
    public static void Main()
    {
    var catshelter = new Shelter<Cat>(new Cat());
    catshelter.SetContents(new Cat());
    catshelter.SetContents(new Lion()); // Is disallowed by the compiler
    }
    }


    Example on DotNetFiddle



    The same pattern is followed by many CLR classes under System.Collections.Generic. Lots of classes implement IEnumerable<T>, which is covariant; but if you want to call the methods that allow you to add, you have to reference it as a concrete class such as List<T>. Or if you really want to add via an interface you could use IList<T>. But in no case is there a single covariant interface that also allows you to add.






    share|improve this answer














    In a case like this, just remove the setter from the interface and use the concrete type (or infer it using var as in this example). After all, if the code "knows" for sure it is adding a cat, it probably also knows the shelter's concrete type.



    interface IShelter<out AnimalType>
    {
    AnimalType Contents { get; }
    }

    class Shelter<AnimalType> : IShelter<AnimalType>
    {
    public Shelter(AnimalType animal)
    {
    }

    public void SetContents(AnimalType newContents)
    {
    Contents = newContents;
    }

    public AnimalType Contents { get; set; }
    }

    public class Usage
    {
    public static void Main()
    {
    var catshelter = new Shelter<Cat>(new Cat());
    catshelter.SetContents(new Cat());
    catshelter.SetContents(new Lion()); // Is disallowed by the compiler
    }
    }


    Example on DotNetFiddle



    The same pattern is followed by many CLR classes under System.Collections.Generic. Lots of classes implement IEnumerable<T>, which is covariant; but if you want to call the methods that allow you to add, you have to reference it as a concrete class such as List<T>. Or if you really want to add via an interface you could use IList<T>. But in no case is there a single covariant interface that also allows you to add.







    share|improve this answer














    share|improve this answer



    share|improve this answer








    edited Nov 8 at 11:49

























    answered Nov 8 at 10:24









    John Wu

    28.5k42651




    28.5k42651












    • Neat. It still bothers me though to have a property with only a getter and an extra method for setting it. One could skip the setter altogether, as the animal is provided with the constructor (which would make it immutable), or also provide a GetContents method to make it more symmetric. Just a personal opinion.
      – marsze
      Nov 8 at 11:52






    • 1




      I would change a lot of things (TAnimal instead of AnimalType for one) but the code is based on the OP's original example, modified only to demonstrate the principle.
      – John Wu
      Nov 8 at 12:08










    • Yeah my comment was primarily meant for OP rather than you. Great answer, esp. the explanations about how it's solved in the framework.
      – marsze
      Nov 8 at 12:12










    • Indeed, I prefer using a setter as well. The seperate function was just so that it can accept object and cast it, as I had thought was necessary. Also, it was really helpful to point out that List<T> already does this with respect to IEnumerable<T>. I use those classes every day but somehow missed that fact.
      – TamaMcGlinn
      Nov 8 at 19:55


















    • Neat. It still bothers me though to have a property with only a getter and an extra method for setting it. One could skip the setter altogether, as the animal is provided with the constructor (which would make it immutable), or also provide a GetContents method to make it more symmetric. Just a personal opinion.
      – marsze
      Nov 8 at 11:52






    • 1




      I would change a lot of things (TAnimal instead of AnimalType for one) but the code is based on the OP's original example, modified only to demonstrate the principle.
      – John Wu
      Nov 8 at 12:08










    • Yeah my comment was primarily meant for OP rather than you. Great answer, esp. the explanations about how it's solved in the framework.
      – marsze
      Nov 8 at 12:12










    • Indeed, I prefer using a setter as well. The seperate function was just so that it can accept object and cast it, as I had thought was necessary. Also, it was really helpful to point out that List<T> already does this with respect to IEnumerable<T>. I use those classes every day but somehow missed that fact.
      – TamaMcGlinn
      Nov 8 at 19:55
















    Neat. It still bothers me though to have a property with only a getter and an extra method for setting it. One could skip the setter altogether, as the animal is provided with the constructor (which would make it immutable), or also provide a GetContents method to make it more symmetric. Just a personal opinion.
    – marsze
    Nov 8 at 11:52




    Neat. It still bothers me though to have a property with only a getter and an extra method for setting it. One could skip the setter altogether, as the animal is provided with the constructor (which would make it immutable), or also provide a GetContents method to make it more symmetric. Just a personal opinion.
    – marsze
    Nov 8 at 11:52




    1




    1




    I would change a lot of things (TAnimal instead of AnimalType for one) but the code is based on the OP's original example, modified only to demonstrate the principle.
    – John Wu
    Nov 8 at 12:08




    I would change a lot of things (TAnimal instead of AnimalType for one) but the code is based on the OP's original example, modified only to demonstrate the principle.
    – John Wu
    Nov 8 at 12:08












    Yeah my comment was primarily meant for OP rather than you. Great answer, esp. the explanations about how it's solved in the framework.
    – marsze
    Nov 8 at 12:12




    Yeah my comment was primarily meant for OP rather than you. Great answer, esp. the explanations about how it's solved in the framework.
    – marsze
    Nov 8 at 12:12












    Indeed, I prefer using a setter as well. The seperate function was just so that it can accept object and cast it, as I had thought was necessary. Also, it was really helpful to point out that List<T> already does this with respect to IEnumerable<T>. I use those classes every day but somehow missed that fact.
    – TamaMcGlinn
    Nov 8 at 19:55




    Indeed, I prefer using a setter as well. The seperate function was just so that it can accept object and cast it, as I had thought was necessary. Also, it was really helpful to point out that List<T> already does this with respect to IEnumerable<T>. I use those classes every day but somehow missed that fact.
    – TamaMcGlinn
    Nov 8 at 19:55












    up vote
    0
    down vote













    The only solution I could think of so far would be using 2 separate interfaces for each of your concerns (IShelter and ISpecificShelter):



    // this replaces IShelter<Animal>
    public interface IShelter
    {
    Animal Animal { get; set; }
    }

    // this replaces IShelter<SpecificAnimal>
    public interface ISpecificShelter<AnimalType> : IShelter where AnimalType : Animal
    {
    new AnimalType Animal { get; set; }
    }

    // implementation
    public class Shelter<AnimalType> : ISpecificShelter<AnimalType> where AnimalType : Animal
    {
    private Animal _animal;

    // explicit implementation, so the correct implementation is called depending on what interface is used
    Animal IShelter.Animal { get { return _animal; } set { _animal = value; } }
    AnimalType ISpecificShelter<AnimalType>.Animal { get { return (AnimalType)_animal; } set { _animal = value; } }

    public Shelter()
    { }
    }


    Usage:



    // specific animal
    ISpecificShelter<Cat> catShelter = new Shelter<Cat>();
    catShelter.Animal = new Cat();
    catShelter.Animal = new Lion(); // => compiler error!
    Cat cat = catShelter.Animal;

    // cast to general interface
    IShelter shelter = catShelter;
    Animal animal = shelter.Animal;


    If you want to prevent instancing the class directly, but only work with the interfaces, you could implement a factory pattern:



    public static class Shelter
    {
    public static IShelter Create()
    {
    return new Implementation<Animal>();
    }

    public static IShelter Create(Animal animal)
    {
    return new Implementation<Animal>(animal);
    }

    public static ISpecificShelter<AnimalType> Create<AnimalType>() where AnimalType : Animal
    {
    return new Implementation<AnimalType>();
    }

    public static ISpecificShelter<AnimalType> Create<AnimalType>(AnimalType animal) where AnimalType : Animal
    {
    return new Implementation<AnimalType>(animal);
    }

    private class Implementation<AnimalType> : ISpecificShelter<AnimalType> where AnimalType : Animal
    {
    private Animal _animal;

    Animal IShelter.Animal { get { return _animal; } set { _animal = value; } }
    AnimalType ISpecificShelter<AnimalType>.Animal { get { return (AnimalType)_animal; } set { _animal = value; } }

    public Implementation()
    { }

    public Implementation(AnimalType animal)
    {
    _animal = animal;
    }
    }
    }


    Usage:



    var shelter = Shelter.Create();
    shelter.Animal = new Lion();
    // OR:
    // var shelter = Shelter.Create(new Lion());
    var animal = shelter.Animal;

    var catShelter = Shelter.Create<Cat>();
    catShelter.Animal = new Cat();
    // OR:
    // var catShelter = Shelter.Create(new Cat());
    var cat = catShelter.Animal;

    // cast is also possible:
    shelter = (IShelter)catShelter;


    It really depends on your specific use cases. You should provide more examples and information on what exactly you want to do and why.






    share|improve this answer























    • Essentially your answer is the same as John Wu's; it's just that his is more succinct because he leaves out the ISpecificShelter and refers directly to Shelter. It's a shame you got downvoted despite being the first to post a correct solution.
      – TamaMcGlinn
      Nov 8 at 19:58










    • @TamaMcGlinn I would have liked to know why. I am always open for positive critcism and suggestions to improve. I really like @JohnWu`s answer best, but I think my design isn't so bad either.
      – marsze
      Nov 8 at 20:05















    up vote
    0
    down vote













    The only solution I could think of so far would be using 2 separate interfaces for each of your concerns (IShelter and ISpecificShelter):



    // this replaces IShelter<Animal>
    public interface IShelter
    {
    Animal Animal { get; set; }
    }

    // this replaces IShelter<SpecificAnimal>
    public interface ISpecificShelter<AnimalType> : IShelter where AnimalType : Animal
    {
    new AnimalType Animal { get; set; }
    }

    // implementation
    public class Shelter<AnimalType> : ISpecificShelter<AnimalType> where AnimalType : Animal
    {
    private Animal _animal;

    // explicit implementation, so the correct implementation is called depending on what interface is used
    Animal IShelter.Animal { get { return _animal; } set { _animal = value; } }
    AnimalType ISpecificShelter<AnimalType>.Animal { get { return (AnimalType)_animal; } set { _animal = value; } }

    public Shelter()
    { }
    }


    Usage:



    // specific animal
    ISpecificShelter<Cat> catShelter = new Shelter<Cat>();
    catShelter.Animal = new Cat();
    catShelter.Animal = new Lion(); // => compiler error!
    Cat cat = catShelter.Animal;

    // cast to general interface
    IShelter shelter = catShelter;
    Animal animal = shelter.Animal;


    If you want to prevent instancing the class directly, but only work with the interfaces, you could implement a factory pattern:



    public static class Shelter
    {
    public static IShelter Create()
    {
    return new Implementation<Animal>();
    }

    public static IShelter Create(Animal animal)
    {
    return new Implementation<Animal>(animal);
    }

    public static ISpecificShelter<AnimalType> Create<AnimalType>() where AnimalType : Animal
    {
    return new Implementation<AnimalType>();
    }

    public static ISpecificShelter<AnimalType> Create<AnimalType>(AnimalType animal) where AnimalType : Animal
    {
    return new Implementation<AnimalType>(animal);
    }

    private class Implementation<AnimalType> : ISpecificShelter<AnimalType> where AnimalType : Animal
    {
    private Animal _animal;

    Animal IShelter.Animal { get { return _animal; } set { _animal = value; } }
    AnimalType ISpecificShelter<AnimalType>.Animal { get { return (AnimalType)_animal; } set { _animal = value; } }

    public Implementation()
    { }

    public Implementation(AnimalType animal)
    {
    _animal = animal;
    }
    }
    }


    Usage:



    var shelter = Shelter.Create();
    shelter.Animal = new Lion();
    // OR:
    // var shelter = Shelter.Create(new Lion());
    var animal = shelter.Animal;

    var catShelter = Shelter.Create<Cat>();
    catShelter.Animal = new Cat();
    // OR:
    // var catShelter = Shelter.Create(new Cat());
    var cat = catShelter.Animal;

    // cast is also possible:
    shelter = (IShelter)catShelter;


    It really depends on your specific use cases. You should provide more examples and information on what exactly you want to do and why.






    share|improve this answer























    • Essentially your answer is the same as John Wu's; it's just that his is more succinct because he leaves out the ISpecificShelter and refers directly to Shelter. It's a shame you got downvoted despite being the first to post a correct solution.
      – TamaMcGlinn
      Nov 8 at 19:58










    • @TamaMcGlinn I would have liked to know why. I am always open for positive critcism and suggestions to improve. I really like @JohnWu`s answer best, but I think my design isn't so bad either.
      – marsze
      Nov 8 at 20:05













    up vote
    0
    down vote










    up vote
    0
    down vote









    The only solution I could think of so far would be using 2 separate interfaces for each of your concerns (IShelter and ISpecificShelter):



    // this replaces IShelter<Animal>
    public interface IShelter
    {
    Animal Animal { get; set; }
    }

    // this replaces IShelter<SpecificAnimal>
    public interface ISpecificShelter<AnimalType> : IShelter where AnimalType : Animal
    {
    new AnimalType Animal { get; set; }
    }

    // implementation
    public class Shelter<AnimalType> : ISpecificShelter<AnimalType> where AnimalType : Animal
    {
    private Animal _animal;

    // explicit implementation, so the correct implementation is called depending on what interface is used
    Animal IShelter.Animal { get { return _animal; } set { _animal = value; } }
    AnimalType ISpecificShelter<AnimalType>.Animal { get { return (AnimalType)_animal; } set { _animal = value; } }

    public Shelter()
    { }
    }


    Usage:



    // specific animal
    ISpecificShelter<Cat> catShelter = new Shelter<Cat>();
    catShelter.Animal = new Cat();
    catShelter.Animal = new Lion(); // => compiler error!
    Cat cat = catShelter.Animal;

    // cast to general interface
    IShelter shelter = catShelter;
    Animal animal = shelter.Animal;


    If you want to prevent instancing the class directly, but only work with the interfaces, you could implement a factory pattern:



    public static class Shelter
    {
    public static IShelter Create()
    {
    return new Implementation<Animal>();
    }

    public static IShelter Create(Animal animal)
    {
    return new Implementation<Animal>(animal);
    }

    public static ISpecificShelter<AnimalType> Create<AnimalType>() where AnimalType : Animal
    {
    return new Implementation<AnimalType>();
    }

    public static ISpecificShelter<AnimalType> Create<AnimalType>(AnimalType animal) where AnimalType : Animal
    {
    return new Implementation<AnimalType>(animal);
    }

    private class Implementation<AnimalType> : ISpecificShelter<AnimalType> where AnimalType : Animal
    {
    private Animal _animal;

    Animal IShelter.Animal { get { return _animal; } set { _animal = value; } }
    AnimalType ISpecificShelter<AnimalType>.Animal { get { return (AnimalType)_animal; } set { _animal = value; } }

    public Implementation()
    { }

    public Implementation(AnimalType animal)
    {
    _animal = animal;
    }
    }
    }


    Usage:



    var shelter = Shelter.Create();
    shelter.Animal = new Lion();
    // OR:
    // var shelter = Shelter.Create(new Lion());
    var animal = shelter.Animal;

    var catShelter = Shelter.Create<Cat>();
    catShelter.Animal = new Cat();
    // OR:
    // var catShelter = Shelter.Create(new Cat());
    var cat = catShelter.Animal;

    // cast is also possible:
    shelter = (IShelter)catShelter;


    It really depends on your specific use cases. You should provide more examples and information on what exactly you want to do and why.






    share|improve this answer














    The only solution I could think of so far would be using 2 separate interfaces for each of your concerns (IShelter and ISpecificShelter):



    // this replaces IShelter<Animal>
    public interface IShelter
    {
    Animal Animal { get; set; }
    }

    // this replaces IShelter<SpecificAnimal>
    public interface ISpecificShelter<AnimalType> : IShelter where AnimalType : Animal
    {
    new AnimalType Animal { get; set; }
    }

    // implementation
    public class Shelter<AnimalType> : ISpecificShelter<AnimalType> where AnimalType : Animal
    {
    private Animal _animal;

    // explicit implementation, so the correct implementation is called depending on what interface is used
    Animal IShelter.Animal { get { return _animal; } set { _animal = value; } }
    AnimalType ISpecificShelter<AnimalType>.Animal { get { return (AnimalType)_animal; } set { _animal = value; } }

    public Shelter()
    { }
    }


    Usage:



    // specific animal
    ISpecificShelter<Cat> catShelter = new Shelter<Cat>();
    catShelter.Animal = new Cat();
    catShelter.Animal = new Lion(); // => compiler error!
    Cat cat = catShelter.Animal;

    // cast to general interface
    IShelter shelter = catShelter;
    Animal animal = shelter.Animal;


    If you want to prevent instancing the class directly, but only work with the interfaces, you could implement a factory pattern:



    public static class Shelter
    {
    public static IShelter Create()
    {
    return new Implementation<Animal>();
    }

    public static IShelter Create(Animal animal)
    {
    return new Implementation<Animal>(animal);
    }

    public static ISpecificShelter<AnimalType> Create<AnimalType>() where AnimalType : Animal
    {
    return new Implementation<AnimalType>();
    }

    public static ISpecificShelter<AnimalType> Create<AnimalType>(AnimalType animal) where AnimalType : Animal
    {
    return new Implementation<AnimalType>(animal);
    }

    private class Implementation<AnimalType> : ISpecificShelter<AnimalType> where AnimalType : Animal
    {
    private Animal _animal;

    Animal IShelter.Animal { get { return _animal; } set { _animal = value; } }
    AnimalType ISpecificShelter<AnimalType>.Animal { get { return (AnimalType)_animal; } set { _animal = value; } }

    public Implementation()
    { }

    public Implementation(AnimalType animal)
    {
    _animal = animal;
    }
    }
    }


    Usage:



    var shelter = Shelter.Create();
    shelter.Animal = new Lion();
    // OR:
    // var shelter = Shelter.Create(new Lion());
    var animal = shelter.Animal;

    var catShelter = Shelter.Create<Cat>();
    catShelter.Animal = new Cat();
    // OR:
    // var catShelter = Shelter.Create(new Cat());
    var cat = catShelter.Animal;

    // cast is also possible:
    shelter = (IShelter)catShelter;


    It really depends on your specific use cases. You should provide more examples and information on what exactly you want to do and why.







    share|improve this answer














    share|improve this answer



    share|improve this answer








    edited Nov 8 at 10:40

























    answered Nov 8 at 9:21









    marsze

    3,89631639




    3,89631639












    • Essentially your answer is the same as John Wu's; it's just that his is more succinct because he leaves out the ISpecificShelter and refers directly to Shelter. It's a shame you got downvoted despite being the first to post a correct solution.
      – TamaMcGlinn
      Nov 8 at 19:58










    • @TamaMcGlinn I would have liked to know why. I am always open for positive critcism and suggestions to improve. I really like @JohnWu`s answer best, but I think my design isn't so bad either.
      – marsze
      Nov 8 at 20:05


















    • Essentially your answer is the same as John Wu's; it's just that his is more succinct because he leaves out the ISpecificShelter and refers directly to Shelter. It's a shame you got downvoted despite being the first to post a correct solution.
      – TamaMcGlinn
      Nov 8 at 19:58










    • @TamaMcGlinn I would have liked to know why. I am always open for positive critcism and suggestions to improve. I really like @JohnWu`s answer best, but I think my design isn't so bad either.
      – marsze
      Nov 8 at 20:05
















    Essentially your answer is the same as John Wu's; it's just that his is more succinct because he leaves out the ISpecificShelter and refers directly to Shelter. It's a shame you got downvoted despite being the first to post a correct solution.
    – TamaMcGlinn
    Nov 8 at 19:58




    Essentially your answer is the same as John Wu's; it's just that his is more succinct because he leaves out the ISpecificShelter and refers directly to Shelter. It's a shame you got downvoted despite being the first to post a correct solution.
    – TamaMcGlinn
    Nov 8 at 19:58












    @TamaMcGlinn I would have liked to know why. I am always open for positive critcism and suggestions to improve. I really like @JohnWu`s answer best, but I think my design isn't so bad either.
    – marsze
    Nov 8 at 20:05




    @TamaMcGlinn I would have liked to know why. I am always open for positive critcism and suggestions to improve. I really like @JohnWu`s answer best, but I think my design isn't so bad either.
    – marsze
    Nov 8 at 20:05










    up vote
    0
    down vote













    What you are trying to achieve is not possible, because technically you want to have interface which is both covariant and contravariant. Limitations of each type of variance are well explained here in this SO answer



    So, if you want to be able to set more derived type (e.g TDerived : T) to the Contents property, you should use contravariant interface:



    public interface IShelter<in T>
    {
    T Contents { set; }
    }


    On the other hand, if you want to be able to pass Contents to less derived type (e.g. T : TBase), you should stick with your current implementation:



    public interface IShelter<out T>
    {
    T Contents { get; }
    }


    Any other combination would result in possible runtime errors, that's why the compiler doesn't allow you to have an interface which is both co- and contravariant.



    So, either use two distinct interfaces to achieve what you want, or rethink/polish your architecture around these types.






    share|improve this answer



























      up vote
      0
      down vote













      What you are trying to achieve is not possible, because technically you want to have interface which is both covariant and contravariant. Limitations of each type of variance are well explained here in this SO answer



      So, if you want to be able to set more derived type (e.g TDerived : T) to the Contents property, you should use contravariant interface:



      public interface IShelter<in T>
      {
      T Contents { set; }
      }


      On the other hand, if you want to be able to pass Contents to less derived type (e.g. T : TBase), you should stick with your current implementation:



      public interface IShelter<out T>
      {
      T Contents { get; }
      }


      Any other combination would result in possible runtime errors, that's why the compiler doesn't allow you to have an interface which is both co- and contravariant.



      So, either use two distinct interfaces to achieve what you want, or rethink/polish your architecture around these types.






      share|improve this answer

























        up vote
        0
        down vote










        up vote
        0
        down vote









        What you are trying to achieve is not possible, because technically you want to have interface which is both covariant and contravariant. Limitations of each type of variance are well explained here in this SO answer



        So, if you want to be able to set more derived type (e.g TDerived : T) to the Contents property, you should use contravariant interface:



        public interface IShelter<in T>
        {
        T Contents { set; }
        }


        On the other hand, if you want to be able to pass Contents to less derived type (e.g. T : TBase), you should stick with your current implementation:



        public interface IShelter<out T>
        {
        T Contents { get; }
        }


        Any other combination would result in possible runtime errors, that's why the compiler doesn't allow you to have an interface which is both co- and contravariant.



        So, either use two distinct interfaces to achieve what you want, or rethink/polish your architecture around these types.






        share|improve this answer














        What you are trying to achieve is not possible, because technically you want to have interface which is both covariant and contravariant. Limitations of each type of variance are well explained here in this SO answer



        So, if you want to be able to set more derived type (e.g TDerived : T) to the Contents property, you should use contravariant interface:



        public interface IShelter<in T>
        {
        T Contents { set; }
        }


        On the other hand, if you want to be able to pass Contents to less derived type (e.g. T : TBase), you should stick with your current implementation:



        public interface IShelter<out T>
        {
        T Contents { get; }
        }


        Any other combination would result in possible runtime errors, that's why the compiler doesn't allow you to have an interface which is both co- and contravariant.



        So, either use two distinct interfaces to achieve what you want, or rethink/polish your architecture around these types.







        share|improve this answer














        share|improve this answer



        share|improve this answer








        edited Nov 8 at 12:08









        TamaMcGlinn

        430315




        430315










        answered Nov 8 at 10:01









        Darjan Bogdan

        2,16311224




        2,16311224






























             

            draft saved


            draft discarded



















































             


            draft saved


            draft discarded














            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53204536%2fhow-can-i-add-a-type-invariant-setter-to-a-covariant-interface%23new-answer', 'question_page');
            }
            );

            Post as a guest




















































































            Popular posts from this blog

            Guess what letter conforming each word

            Port of Spain

            Run scheduled task as local user group (not BUILTIN)