Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Are there any rules for type conversion between C# generics?

Tags:

c#

generics

I'm having an interface IJob from which all Job classes inherits and I have generic repo class which will process all kind of IJob's.

The problem im facing is im not able to able convert Repository<Job1> to Repository<IJob> even though Job1 is a type of IJob.

Code

internal class Program
{
    public interface IJob { }
    public class Job1 : IJob { }
    public class Job2 : IJob { }

    public class Repository<TJob>
        where TJob : IJob
    {
        public List<TJob> GetJobs()
        {
            return new List<TJob>();
        }
    }

    private static void Main(string[] args)
    {
        IJob iJob = new Job1(); // Valid
        Repository<IJob> repo = new Repository<Job1>(); // Not Valid
    }
}

Can someone let me know why this wont be possible in C# and are there any other rules type conversion in C# generics?

like image 437
Umamaheswaran Avatar asked Mar 16 '16 14:03

Umamaheswaran


People also ask

Is type conversion possible in C?

Typecasting is a method in C language of converting one data type to another. There are two types of typecasting. 1. Implicit Type casting − This conversion is done by the compiler.

What type of conversion is acceptable in C language?

Explicit Type Conversion In C // explicit type conversion double value = (double) number; Here, (double) - represents the data type to which number is to be converted. number - value that is to be converted to double type.

How are type conversions handled by C?

Type Casting is basically a process in C in which we change a variable belonging to one data type to another one. In type casting, the compiler automatically changes one data type to another one depending on what we want the program to do.

Which type conversion is not accepted in C?

Which type of conversion is NOT accepted? Explanation: Conversion of a float to pointer type is not allowed.


2 Answers

If you want covariance, then you'll have to introduce a generic interface for the repository and change the return type of the GetJobs method to IEnumerable<TJob>:

internal class Program
{
    public interface IJob { }
    public class Job1 : IJob { }
    public class Job2 : IJob { }

    public interface IRepository<out TJob> where TJob : IJob
    {
        IEnumerable<TJob> GetJobs();
    }

    public class Repository<TJob> : IRepository<TJob> where TJob : IJob
    {
        public IEnumerable<TJob> GetJobs()
        {
            return new List<TJob>();
        }
    }

    private static void Main(string[] args)
    {
        IJob iJob = new Job1(); // Valid
        IRepository<IJob> repo = new Repository<Job1>(); // Also valid
    }
}

For more information about covariance and contravariance, see: https://msdn.microsoft.com/en-us/library/dd799517%28v=vs.110%29.aspx

like image 187
Eiríkur Fannar Torfason Avatar answered Sep 28 '22 02:09

Eiríkur Fannar Torfason


Repository<IJob> repo = new Repository<Job1>(); // Not Valid

Yes, because it isn't an Repository<IJob>. With an Repository<IJob>, this line would be valid:

repo.GetJobs().Add(new Job2());

Now, with a Repository<Job1>, this line is invalid. It won't compile.

So the error you get is correct. A Repository<Job1> is not a Repository<IJob>.

like image 38
nvoigt Avatar answered Sep 28 '22 01:09

nvoigt