简体   繁体   中英

How to use generic in c# to call c-functions

I have two functions which calls c-function inside

void do_double(double[] p1)
{
    // some c-function called with (double*)
}

void do_float(float[] p1)
{
    // some c-function called with (float*)
}

Instead of do_float and do_double I want to create some generic parameter method to call this c-functions. For example:

void do_generic<T>(T[] p1)
{
    if (typeof(T) == typeof(float))
        do_float(T);
    else if ( ...double)
        do_double(T);
}

What is the best way to do this? Converting T to float/double does not seem to be right way.

This is a typical code smell scenario. This kind of type switching doesn't scale. The solution would be generalization or overloading.

Method overloading:

class DoSomething
{
  public void Do(double[] args)
  {
    do_double(args);
  }

  public void Do(float[] args)
  {
    do_float(args);
  }

  public void Do(int[] args)
  {
    do_int(args);
  }
}

Or generalization and provide an implementation that knows exactly how to handle a certain argument type:

interface IDoSomething<T>
{
  void Do(T[] args);
}

class DoDouble : IDoSomething<double>
{
  public void Do(double[] args)
  {
    do_double(args);
  }
}

class DoFloat : IDoSomething<float>
{
  public void Do(float[] args)
  {
    do_float(args);
  }
}

Using generics here is wrong. You are doing a runtime check of the type inside the do_generic which beats the purpose of generic.

I think it's better to use method overloading. Just create two methods with the same name and different parameter type:

void do_generic(double[] p1) { … }

void do_generic(float[] p1) { … }

You have a nicer API and a compile time parameter check.

You effectively have 2 options:

Create an overload for each type - this keeps all checks at compile time, but has non-trivial annoyance of having to create each overload if there are many many types.

Use generics and switch on the typeof(T) as you currently do. This is also zero-cost, like the overloads, as the JIT will resolve these branches at JIT time for the specialised method and elide the unnecessary branches. However, this does mean that invalid types may be provided. If there is a path for an unknown T (which should be constrained to be unmanaged for marshalling reasons), then this works, else, you will have to throw some kind of exception when an invalid T is provided, which moves the compile-time checking of overloading to runtime, which is less than ideal

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM