一个(可能)非常普遍的数字问题 [英] A (probably) quite common problem with numerics
问题描述
所以我在处理数字时遇到了一个小问题.我真的无法想象我是唯一遇到此问题的人,但是我找不到任何解决方案.这样就可以了.
我正在制作属性 [字节 [ ^ ],SByte
, Int16 [ UInt16 [ ^ ], Double [ ^ ], ^ ] ...您明白了.
那我注定要创建11个重载的构造函数(实际上是22个,因为我的构造函数已经有重载了)?
并将数字传递给构造函数后,我该如何处理呢?我是否还会创建11个可以容纳每个数字的私有字段,还是应该将其放入对象 [ ^ ]?
无论如何,我都需要一个很大的案例 [开关 [ Int64 [ UInt64 [解决方案
通常通常对属性进行一次处理(类型询问等),因此性能并不重要,因此装箱是减少代码大小的可行选择. >
恐怕您无法逃避大的switch语句[或嵌套的IF](如果您可以让我知道!我已经尝试过:) [RaptorDB Doc存储中的DataTypes.cs].)
<据我所知,没有办法拥有一个单一的构造函数.使用 ValueType [ValueType [异常 [ ^ ]).通过将数字作为 IComparable [IComparable [ IComparable.CompareTo [ ^ ]将该值与我得到的任何其他数字进行比较.这为我节省了大量的case语句(我不再对类型感兴趣,因为我仍然可以进行比较).
当然,这只能工作,因为我不必加,减等,只需要比较即可.仍然欢迎其他任何技巧,窍门,解决方案等.尤其是在我仍如何仅使用单个类型而不是11 ...的加法,减法等方面.
谢谢大家到目前为止的帮助!
dynamic
怎么样?
如果您愿意支付运行时成本,并且愿意放弃编译时类型检查,那么dynamic
可能会有所帮助.
C#确实缺乏泛型专门知识,并且(尤其是在运行时性能很重要的情况下)缺少泛型的编译时详细说明.
在C ++中,您可以基于在编译时阐述的模板来构建 type traits (例如,关于该特性的开创性书籍现在仍然是 ^ ]).
该概念基于三个方面:
- 模板编程的功能性编程风格
- 在模板化项目中定义默认行为,为相关类型(例如,几种数字类型)添加专门化
- C ++允许具有值作为模板参数(例如,不仅类型,而且还包括编译时常量)
好吧,C#甚至还没有达到这个目的:-(
坦白说,我真的不喜欢这种解决方法",但是您至少还有另一种选择可以评估您的问题.
干杯
安迪
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 aPrivate 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 aboutdynamic
?
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:
- functional programming style for template programming
- define default behavior in a templated item, add specialization for the types in question (e.g. for the several numeric types)
- 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屋!