简单的通用功能 [英] Simple Generic Function

查看:85
本文介绍了简单的通用功能的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有人可以帮我理解我想做什么是可能的吗?



我有一个简单的通用方法:



Could someone help me to understand if what I want to do is possible?

I have a simple generic method:

public T DivideByTwo<T>(T number)
{
     T two = (T)Convert.ChangeType(2, typeof(T));

     T result = DIVIDE(number, two);

     return result;
}





我可以这样称呼它没问题:







I can call it like this no problem:


ParallelNumber<double> parallelNumber = new ParallelNumber<double>();

double result = parallelNumber.DivideByTwo(3);





我当然可以使用int,uint等等。



但我不能如下所示:





And of course I can use int,uint etc etc.

But I cannot call it as follows:

ParallelNumber<BigInteger> parallelNumber = new ParallelNumber<BigInteger>();

BigInteger result = parallelNumber.DivideByTwo(3);





失败的行是:



T two =(T)Convert.ChangeType(2,typeof(T));



抛出InvalidCastException。从System.Int32到System.Numerics.BigInteger的无效演员



我可以使我的方法足够通用以处理BigInteger吗?



(DIVIDE函数只需要两个泛型参数并返回一个泛型)



The line which fails is:

T two = (T)Convert.ChangeType(2, typeof(T));

Throws InvalidCastException. Invalid cast from System.Int32 to System.Numerics.BigInteger

Can I make my method generic enough to handle BigInteger?

(The DIVIDE function just takes two generic arguments and returns a generic)

推荐答案

Hi,

Thanks for all the answers. Here's my solution so far. It is simpler to code than the accepted solution recommended by AspDotNetDev, and I think would be faster. Can anyone advise me further or is what I have as good as it will get?

I have a generic class defined as follows:

 public class ParallelNumber<T>
 {
     private T GENERIC_TWO;

     private Func<T,T,T> DIVIDE = null;

      public ParallelNumber()
      {
            CreateDivideFunction();

            if (typeof(T) == typeof(BigInteger))
            {
                GENERIC_TWO = (T)Convert.ChangeType((BigInteger)2, typeof(T));
            }
            else
            {
                GENERIC_TWO = (T)Convert.ChangeType(2, typeof(T));
            }
      }

      private void CreateDivideFunction()
      {
            ParameterExpression paramA = Expression.Parameter(typeof(T), "a"), paramB = Expression.Parameter(typeof(T), "b");

            BinaryExpression body = Expression.Divide(paramA, paramB);

            DIVIDE = Expression.Lambda<Func<T, T, T>>(body, paramA, paramB).Compile();
       }

       public T DivideByTwo(T number)
       {
            T result = DIVIDE(number, GENERIC_TWO);

            return result;
       }
 }

The last function DivideByTwo is the one which can now be called with any numeric type.

Would anyone else endorse this method and if so would they suggest improvements or would anyone go down a completely different root.

This method takes about 100 times longer to run than one written using (say) uint instead of generics. Can I hope to match performance using generics instead on (say) uint.

It would be ideal if at runtime, after having used the above function as follows:

ParallelNumber<uint> parallelNumber = new ParallelNumber<uint>();
uint d = parallelNumber.DivideByTwo(50);

it ran as fast as calling the function written with uint instead of generics. But then of course it ran slower when called as:

ParallelNumber<BigInteger> parallelNumber = new ParallelNumber<BigInteger>();
BigInteger d = parallelNumber.DivideByTwo(50);

Thanks for any help,
Mitch.


 HERE's the rest of the text which the preview ingored :(

(body,paramA,paramB).Compile();
       }

       public T DivideByTwo(T number)
       {
            T result = DIVIDE(number, GENERIC_TWO);

            return result;
       }
 }

The last function DivideByTwo is the one which can now be called with any numeric type.

Would anyone else endorse this method and if so would they suggest improvements or would anyone go down a completely different root.

This method takes about 100 times longer to run than one written using (say) uint instead of generics. Can I hope to match performance using generics instead on (say) uint.

It would be ideal if at runtime, after having used the above function as follows:

ParallelNumber<uint> parallelNumber = new ParallelNumber<uint>();
uint d = parallelNumber.DivideByTwo(50);

it ran as fast as calling the function written with uint instead of generics. But then of course it ran slower when called as:

ParallelNumber<BigInteger> parallelNumber = new ParallelNumber<BigInteger>();
BigInteger d = parallelNumber.DivideByTwo(50);

Thanks for any help,
Mitch.


我推荐以下方法。



I recommend the following approach.

  1. 检测Convert.ChangeType是否有效。您可能只是尝试它并捕获异常(这将是最简单的方法)。但是,可能有一种方法可以使用IConvertible检查转换,而不会抛出异常。我会留给您深入了解。
  2. 如果Convert.ChangeType不起作用,请使用反射来检查类型是否具有接受整数的构造函数。然后,您可以使用反射创建该类型的实例,并将整数传递给构造函数。这也可以用表达式树来实现,但我不确定它是如何工作的(虽然这可能是一种更优化的方法)。
  3. 如果没有合适的构造函数,你可能想要使用反射以检查是否存在来自int的隐式转换运算符 ,然后使用反射来执行对该类型的新实例的赋值。
  1. Detect if Convert.ChangeType will work. You might just try it and catch the exception (that''d be the easiest way). However, there may be a way to use IConvertible to check the conversion without an exception being thrown. I''ll leave this to you to dive deeper into.
  2. If Convert.ChangeType doesn''t work, use reflection to check if the type has a constructor that accepts an integer. You can then use reflection to create an instance of that type and pass the integer to the constructor. This may also be possible with expression trees, but I''m not really sure how that works (though that may be a more optimal approach).
  3. If there is no appropriate constructor, you may want to use reflection to check if there is an implicit conversion operator from an int, then use reflection to perform the assignment to a new instance of the type.


这篇关于简单的通用功能的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆