Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C# Using generics and interface implementation

Tags:

c#

.net

generics

Context: .NET 4.0, C#

I'm creating a set of interfaces and a set of clases that implement them to provide some service. The clients use the concrete clases but call methods that are declared using the interfaces as parameter types.

A simplified example is this one:

namespace TestGenerics
{
    // Interface, of fields
    interface IField
    {
    }

    // Interface: Forms (contains fields)
    interface IForm<T> where T : IField
    {

    }

    // CONCRETE CLASES
    class Field : IField
    {   
    }

    class Form <T> : IForm<T> where T : IField
    {
    }

    // TEST PROGRAM
    class Program
    {
        // THIS IS THE SIGNATURE OF THE METHOD I WANT TO CALL
        // parameters are causing the error.
        public static void TestMethod(IForm<IField> form)
        {
            int i = 1;
            i = i * 5;
        }

        static void Main(string[] args)
        {
            Form<Field> b = new Form<Field>();
            Program.TestMethod(b);
        }
    }
}

The code makes sense to me, but I get the compiler error:

Argument 1: cannot convert from 'TestGenerics.Form<TestGenerics.Field>' to 'TestGenerics.IForm<TestGenerics.IField>' TestGenerics

I'm not sure what I'm doing wrong, I've read lots of pages on the internet but none solved my problem.

Is there a solution that would not modify that much the architecture of what I'm trying to build:

Edit:I designed the interfaces in a way such that they should be independent of concrete clases that implement them. The concrete clases could be loaded from a dll, but most of the application Works with the interfaces. In some cases I need to use concrete clases, specially when using clases that need to be serialized.

Thanks in advance.

Alejandro

like image 595
Sugar Avatar asked Jul 30 '13 15:07

Sugar


People also ask

What C is used for?

C programming language is a machine-independent programming language that is mainly used to create many types of applications and operating systems such as Windows, and other complicated programs such as the Oracle database, Git, Python interpreter, and games and is considered a programming foundation in the process of ...

What is the full name of C?

In the real sense it has no meaning or full form. It was developed by Dennis Ritchie and Ken Thompson at AT&T bell Lab. First, they used to call it as B language then later they made some improvement into it and renamed it as C and its superscript as C++ which was invented by Dr. Stroustroupe.

Is C language easy?

C is a general-purpose language that most programmers learn before moving on to more complex languages. From Unix and Windows to Tic Tac Toe and Photoshop, several of the most commonly used applications today have been built on C. It is easy to learn because: A simple syntax with only 32 keywords.

Is C programming hard?

C is more difficult to learn than JavaScript, but it's a valuable skill to have because most programming languages are actually implemented in C. This is because C is a “machine-level” language. So learning it will teach you how a computer works and will actually make learning new languages in the future easier.


2 Answers

The problem is that Form<Field> implements IForm<Field> but not IForm<IField>. You cannot use an inherited class (or interface) as a generic parameter unless it is marked as covariant with the out identifier. However, marking your interface as covariant will restrict the usage significantly (basically making in an "output-only" interface like IEnumerable) so it may not work for you.

One way to get it to work is to make TestMethod generic as well:

public static void TestMethod<T>(IForm<T> form) where T:IField
{
    int i = 1;
    i = i * 5;
}
like image 185
D Stanley Avatar answered Oct 07 '22 01:10

D Stanley


You can use Covariance, like so:

interface IForm<out T> where T : IField
{

}

More about Covariance and Contravariance here.

like image 28
Tamim Al Manaseer Avatar answered Oct 07 '22 00:10

Tamim Al Manaseer