一个(可能)非常普遍的数字问题 [英] A (probably) quite common problem with numerics

查看:89
本文介绍了一个(可能)非常普遍的数字问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

所以我在处理数字时遇到了一个小问题.我真的无法想象我是唯一遇到此问题的人,但是我找不到任何解决方案.这样就可以了.

我正在制作属性 [字节 [ ^ ],SByte Int16 [ UInt16 [ ^ ], Double [ ^ ],对象 [ ^ ]?

无论如何,我都需要一个很大的案例 [开关 [ Int64 [ UInt64 [解决方案

通常通常对属性进行一次处理(类型询问等),因此性能并不重要,因此装箱是减少代码大小的可行选择. >
恐怕您无法逃避大的switch语句[或嵌套的IF](如果您可以让我知道!我已经尝试过:) [RaptorDB Doc存储中的DataTypes.cs].)


<据我所知,没有办法拥有一个单一的构造函数.使用
ValueType [ValueType [异常 [ ^ ]).通过将数字作为 IComparable [IComparable [ IComparable.CompareTo [ ^ ]将该值与我得到的任何其他数字进行比较.这为我节省了大量的case语句(我不再对类型感兴趣,因为我仍然可以进行比较).
当然,这只能工作,因为我不必加,减等,只需要比较即可.仍然欢迎其他任何技巧,窍门,解决方案等.尤其是在我仍如何仅使用单个类型而不是11 ...的加法,减法等方面.
谢谢大家到目前为止的帮助!


dynamic怎么样?
如果您愿意支付运行时成本,并且愿意放弃编译时类型检查,那么dynamic可能会有所帮助.

C#确实缺乏泛型专门知识,并且(尤其是在运行时性能很重要的情况下)缺少泛型的编译时详细说明.

在C ++中,您可以基于在编译时阐述的模板来构建 type traits (例如,关于该特性的开创性书籍现在仍然是
干杯
安迪

PS:这里有一些示例代码:

 [AttributeUsage(AttributeTargets.Class)]
公共  MyAttrAttribute:属性
{
    公共 动态 Arg { get ; 私有 设置; } // 动态属性
    公共 MyAttrAttribute(对象 arg)
    {
        Arg = arg;
    }
    公共 静态 MyAttrAttribute GetAttribute(类型所有者)
    {
        返回(来自所有者中的所有者.GetCustomAttributes (错误)
                其中 a.GetType()==  typeof (MyAttrAttribute)
                选择一个
                ).FirstOrDefault() as  MyAttrAttribute;
    }
}

[MyAttr( 123 )]
公共  MyClassWithIntAttr
{
    公共 MyClassWithIntAttr()
    {
         var  attr = MyAttrAttribute.GetAttribute(
                     MethodBase.GetCurrentMethod().DeclaringType);
        Console.WriteLine(" ,attr,attr.Arg +  42 ); // 可能会引发异常
    }
}
[MyAttr( 3 . 14159265358 )]
公共  MyClassWithDoubleAttr
{
    公共 MyClassWithDoubleAttr()
    {
         var  attr = MyAttrAttribute.GetAttribute(
                     MethodBase.GetCurrentMethod().DeclaringType);
        Console.WriteLine(" ,attr,attr.Arg +  42 ); // 可能会引发异常
    }
}

 class 程序
{
    公共 静态  void  Main()
    {
        MyClassWithIntAttr c1 =  MyClassWithIntAttr();
        MyClassWithDoubleAttr c2 =  MyClassWithDoubleAttr();
    } 



输出:

 Sample.MyAttrAttribute = 165
Sample.MyAttrAttribute = 45.14159265358 


So I''m having a small problem when working with numerics. I can''t really imagine that I am the only one with this problem, yet I can''t find any solutions. So here it goes.

I am making an
Attribute[^] which takes a numeric in its constructor (ANY numeric). Now here is the problem, there are 11(!) different types of numerics... Byte[^], SByte, Int16[^], UInt16[^], Double[^], Decimal[^]... You get the point.
So am I doomed to create 11 overloaded constructors (actually 22 since my constructor already had an overload)?
And what do I do with the numeric once it has been passed to my constructor? Do I also create 11 private fields that can hold each numeric or should I box it in an Object[^]?

In any case I will need a huge Case[^]/switch[^] statement later on to check for type of the numeric...
Any solutions for this problem? For example, taking an Int64[^] and UInt64[^] could take care for all non-decimal numerics, but I am not sure if this is good/accepted practice.

Thanks.

解决方案

Usually attributes are processed once (type interrogation etc.) so performance is not critical so boxing is a viable option which reduces your code size.

I am afraid you can not escape a big switch statement [or a nested IF] (if you can let me know! I have tried :) [DataTypes.cs in RaptorDB Doc store]).


As far as I can see there is no way to have one single constructor. Using a ValueType[^] is an idea, but not very user friendly (since ValueType[^] can be more than just numerics, in which case I would have to throw an Exception[^]). By storing the numerics into a Private field as an IComparable[^] (as all numeric types are IComparable[^]) I can then simply call IComparable.CompareTo[^] to compare the value with whatever other numeric I get. This saves me the huge case statement (I am not interested in type anymore, since I can compare anyway).
Of course this only works because I do not have to add, subtract etc. and only need to compare. Any other tips, tricks, solutions etc. are still welcome. Especially on how I could still add, subtract etc. using only a single type and not 11...

Thanks everyone for the help so far!


How about dynamic?
If you are willing to pay the run-time cost, and if you are willing to give up on compile-time type check, dynamic could help.

C# really lacks generics specialization and (especially if run-time performance matters) compile-time elaboration of generics.

In C++ you can build type traits based on templates that were elaborated at compile-time (e.g. a pioneering book on that was and still is Modern C++ Design[^]).

The concept is based on three aspects:


  1. functional programming style for template programming
  2. define default behavior in a templated item, add specialization for the types in question (e.g. for the several numeric types)
  3. C++ allows to have values as template parameters (e.g. not only types but also compile-time constants)



Well, C# does not get even close to this :-(

Top be honest, I really dislike this "workaround", but you have at least another option to evaluate for your problem at hand.

Cheers
Andi

PS: here goes some sample code:

[AttributeUsage(AttributeTargets.Class)]
public class MyAttrAttribute : Attribute
{
    public dynamic Arg { get; private set; } // dynamic attribute
    public MyAttrAttribute(object arg)
    {
        Arg = arg;
    }
    public static MyAttrAttribute GetAttribute(Type owner)
    {
        return (from a in owner.GetCustomAttributes(false)
                where a.GetType() == typeof(MyAttrAttribute)
                select a
                ).FirstOrDefault() as MyAttrAttribute;
    }
}

[MyAttr(123)]
public class MyClassWithIntAttr
{
    public MyClassWithIntAttr()
    {
        var attr = MyAttrAttribute.GetAttribute(
                     MethodBase.GetCurrentMethod().DeclaringType);
        Console.WriteLine("{0} = {1}", attr, attr.Arg + 42); // may throw exception
    }
}
[MyAttr(3.14159265358)]
public class MyClassWithDoubleAttr
{
    public MyClassWithDoubleAttr()
    {
        var attr = MyAttrAttribute.GetAttribute(
                     MethodBase.GetCurrentMethod().DeclaringType);
        Console.WriteLine("{0} = {1}", attr, attr.Arg + 42); // may throw exception
    }
}

class Program
{
    public static void Main()
    {
        MyClassWithIntAttr c1 = new MyClassWithIntAttr();
        MyClassWithDoubleAttr c2 = new MyClassWithDoubleAttr();
    }



Output:

Sample.MyAttrAttribute = 165
Sample.MyAttrAttribute = 45.14159265358


这篇关于一个(可能)非常普遍的数字问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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