Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C# generics method selection

Tags:

c#

generics

I'm trying to write generic algorithms in C# that can work with geometric entities of different dimension.

In the following contrived example I have Point2 and Point3, both implementing a simple IPoint interface.

Now I have a function GenericAlgorithm that calls a function GetDim. There are multiple definitions of this function based on the type. There is also a fall-back function that is defined for anything that implements IPoint.

I initially expected the output of the following program to be 2, 3. However, it is 0, 0.

interface IPoint {
    public int NumDims { get; } 
}

public struct Point2 : IPoint {
    public int NumDims => 2;
}

public struct Point3 : IPoint {
    public int NumDims => 3;
}

class Program
{
    static int GetDim<T>(T point) where T: IPoint => 0;
    static int GetDim(Point2 point) => point.NumDims;
    static int GetDim(Point3 point) => point.NumDims;

    static int GenericAlgorithm<T>(T point) where T : IPoint => GetDim(point);

    static void Main(string[] args)
    {
        Point2 p2;
        Point3 p3;
        int d1 = GenericAlgorithm(p2);
        int d2 = GenericAlgorithm(p3);
        Console.WriteLine("{0:d}", d1);        // returns 0 !!
        Console.WriteLine("{0:d}", d2);        // returns 0 !!
    }
}

OK, so for some reason the concrete type information is lost in GenericAlgorithm. I don't fully understand why this happens, but fine. If I can't do it this way, what other alternatives do I have?

like image 321
mohamedmoussa Avatar asked Feb 26 '20 07:02

mohamedmoussa


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.

What is C language?

C is a structured, procedural programming language that has been widely used both for operating systems and applications and that has had a wide following in the academic community. Many versions of UNIX-based operating systems are written in C.


1 Answers

This method:

static int GenericAlgorithm<T>(T point) where T : IPoint => GetDim(point);

... will always call GetDim<T>(T point). The overload resolution is performed at compile-time, and at that stage there's no other applicable method.

If you want overload resolution to be called at execution time, you'd need to use dynamic typing, e.g.

static int GenericAlgorithm<T>(T point) where T : IPoint => GetDim((dynamic) point);

But it's generally a better idea to use inheritance for this - in your example, obviously you could just have the single method and return point.NumDims. I assume in your real code there's some reason the equivalent is trickier to do, but without more context we can't advise on how to use inheritance to perform the specialization. Those are your options though:

  • Inheritance (preferred) for specialization based on the execution-time type of the target
  • Dynamic typing for execution-time overload resolution
like image 58
Jon Skeet Avatar answered Sep 24 '22 21:09

Jon Skeet