ivymike
ivymike

Reputation: 1591

How to use interface as a generic parameter?

I have a generic class:

class JobDetails<IJobRequirement>{}
class SpecialRequirement: IJobRequirement{}

I'm unable to assign the values of type JobDetails<SpecialRequirement> to variables of type JobDetails<IJobRequirement>. Is this possible in C# or am I missing something basic ?

Upvotes: 0

Views: 120

Answers (2)

Toxantron
Toxantron

Reputation: 2398

Generally Foo<A> and Foo<B> do not share a common ancestry. They share a common generic type definition, but that does not mean they are assignable even if public class B : A.

You seem to be looking for Co- and Contravariance. A mechanism for generics in C# that lets you define compatibility between different types. However this only works for generic interfaces.

For example

public interface IJobDetails<out TRequirement>
   where TRequirement : IJobRequirement
{
    TRequirement Requirement { get; }
}

public class JobDetails<TRequirement> : IJobDetails<TRequirement>
{
    public TRequirement Requirement { get; set; }
}

public void Test()
{
    IJobDetails<IJobRequirement> a = new JobDetails<SpecificRequirement>();
}

However using the modifier in or out limits whether you can use the type only as a return value or a method argument.

This is the reason why you an assign IEnumerable<B> to IEnumerable<A> if public class B : A because IEnumerable is declared as IEnumerable<out T>.

For further information I recommend reading the following Blog: http://tomasp.net/blog/variance-explained.aspx/

Upvotes: 5

junkangli
junkangli

Reputation: 1202

You can put constraints on Type Parameters:

interface IJobRequirement
{ }

class SpecialRequirement : IJobRequirement
{ }

class JobDetails<T> where T : IJobRequirement
{ }

Upvotes: 2

Related Questions