Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

.NET Generic Method Question

Tags:

c#

.net

generics

I'm trying to grasp the concept of .NET Generics and actually use them in my own code but I keep running into a problem.

Can someone try to explain to me why the following setup does not compile?

public class ClassA
{
    ClassB b = new ClassB();

    public void MethodA<T>(IRepo<T> repo) where T : ITypeEntity
    {
        b.MethodB(repo);
    }
}

public class ClassB
{
    IRepo<ITypeEntity> repo;

    public void MethodB(IRepo<ITypeEntity> repo)
    {
        this.repo = repo;
    }
}

I get the following error:
cannot convert from IRepo<'T> to IRepo<'ITypeEntity>

MethodA gets called with a IRepo<'DetailType> object parameter where DetailType inherits from ITypeEntity.

I keep thinking that this should compile as I'm constraining T within MethodA to be of type ITypeEntity.

Any thoughts or feedback would be extremely helpful.

Thanks.

Edit: Nick R has a great suggestion but unfortunately in my context, I don't have the option of making ClassA Generic. ClassB could be though.

like image 317
Gary Brunton Avatar asked Sep 23 '08 22:09

Gary Brunton


People also ask

What are generics in C# Interview Questions?

Q4. What are generics in c#? Ans: Generics refers to the technique of writing the code for a class without specifying the data type(s) that the class works on. It allow you to define type-safe data structures, without committing to actual data types.

What is an advantage of using generics in net?

Generics shift the burden of type safety from you to the compiler. There is no need to write code to test for the correct data type because it is enforced at compile time. The need for type casting and the possibility of run-time errors are reduced. Better performance.

What is generic with example in C#?

Generic is a class which allows the user to define classes and methods with the placeholder. Generics were added to version 2.0 of the C# language. The basic idea behind using Generic is to allow type (Integer, String, … etc and user-defined types) to be a parameter to methods, classes, and interfaces.

How many types of generics are there in C#?

C# allows you to define generic classes, interfaces, abstract classes, fields, methods, static methods, properties, events, delegates, and operators using the type parameter and without the specific data type.


2 Answers

Inheritance doesn't work the same when using generics. As Smashery points out, even if TypeA inherits from TypeB, myType<TypeA> doesn't inherit from myType<TypeB>.

As such, you can't make a call to a method defined as MethodA(myType<TypeB> b) expecting a myType<TypeB> and give it a myType<TypeA> instead. The types in question have to match exactly. Thus, the following won't compile:

myType<TypeA> a; // This should be a myType<TypeB>, even if it contains only TypeA's

public void MethodB(myType<TypeB> b){ /* do stuff */ }

public void Main()
{
  MethodB(a);
}

So in your case, you would need to pass in an IRepo<ITypeEntity> to MethodB, even if it only contains DetailTypes. You'd need to do some conversion between the two. If you were using a generic IList, you might do the following:

public void MethodA<T>(IList<T> list) where T : ITypeEntity
{
  IList<T> myIList = new List<T>();

  foreach(T item in list)
  {
    myIList.Add(item);
  }

  b.MethodB(myIList);
}

I hope this is helpful.

like image 68
Lucas Wilson-Richter Avatar answered Oct 25 '22 15:10

Lucas Wilson-Richter


Well this compiles ok. I basically redifined the classes to take generic parameters. This may be ok in your context.

public interface IRepo<TRepo>
{
}

public interface ITypeEntity
{
}


public class ClassA<T> where T : ITypeEntity
{
    ClassB<T> b = new ClassB<T>();
    public void MethodA(IRepo<T> repo)
    {
        b.MethodB(repo);
    }
}
public class ClassB<T> where T : ITypeEntity
{
    IRepo<T> repo;
    public void MethodB(IRepo<T> repo)
    {
        this.repo = repo;
    }
}
like image 43
Nick Randell Avatar answered Oct 25 '22 15:10

Nick Randell