Int32.Zero的扩展方法 [英] Extension method for Int32.Zero

查看:57
本文介绍了Int32.Zero的扩展方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在.NET Framework中有一个优雅的Decimal.Zero,而不是硬编码0。但是,如果你想将Decimal.Zero分配给一个整数,它涉及如下代码



Instead of hardcoding 0, there is an elegant Decimal.Zero in .NET Framework. However if you want to assign Decimal.Zero to an integer it involves code like below

Int32.Parse(Decimal.Zero.ToString());



我试图看看我们是否可以在Int32上使用扩展方法,如下所示无法让它运作。我缺少什么?




I am trying to see if we can have an extension method on Int32 like below but unable to get it working. What am I missing?

public static int Zero(this Int32 intObject)
        {
            return (0);
        }

推荐答案

请将我的答案视为这个美妙笑话的一部分。



首先,你的 Int32扩展确实有效。由于某种原因,你只是没有看到它。



这是实例方法,但扩展语法和机制模仿实例方法。所以,调用应该是: int something = 0.Zero(); 或者, int somethingElse = 42.Zero(); 实例本身没什么区别,但这只是因为你不使用this intObject 参数。



我觉得你在开玩笑,你明白这个想法是多么荒谬。这不仅仅是因为你必须使用整数对象来拥有一些(未使用过的)实例。情况更糟。当然,将这个功能添加到一个整数类型是没有多大意义的;我们需要涵盖所有类型。让我们从两个开始:



Please consider my answer as a part of this wonderful joke.

First of all, your Int32 extension does work. By some reason, you just failed to see it.

This is the instance method but the extension syntax and mechanism mimic instance method. So, the call should be: int something = 0.Zero(); Or, int somethingElse = 42.Zero(); The instance itself makes no difference, but it''s just because you don''t use "this intObject" parameter.

As I think you are joking, you understand how absurd the idea is. And this is not only because you have to use integer object anyway, to have some (unused) instance. It''s worse. Of course, adding this "functionality" just to one integer type would not make much sense; we need to cover all types. Let''s start with two:

namespace System { // note the elegance and convenience of using this namespace; this is quite a legitimate thing
    public static class SystemExtensions {
            public static int Zero(this int unusedValue) {
                return 0;
            }
            public static uint Zero(this uint unusedValue) {
                return 0;
            }
    } // class SystemExtensions
} // namespace System



到目前为止一切顺利,但是你看到了歧义吗?我们试试吧:


So far so good, but do you see the ambiguity? Let''s try:

int a = 0.Zero();
uint b = 0.Zero(); // this line won't compile!



即使对某些人来说,很明显在第二种情况下,隐含 public static uint Zero(this uint unusedValue),这对编译器来说并不明显。 :-)

这是正确的解决办法:


Even though, to some, it looks apparent that in the second case, public static uint Zero(this uint unusedValue) is implied, this is not apparent to the compiler. :-)
Here is the correct work-around:

int a = ((int)0).Zero();
uint b = ((uint)0).Zero(); // great laconic syntax to write 0, isn't it? :-)



随着每一步,越来越优雅,对吧? :-)



我已经讨论了问题中第一行的优雅。顺便说一句,解决方法非常简单:您应该以相同的扩展方法方式为所有数字类型的零定义所有可能的转换方法。很明显,不是吗?



但是,更不可能更简单了吗?这:


With every step, more and more "elegance", right? :-)

And I already discussed the "elegance" of the very first line shown in the question. By the way, the work-around is really simple: you should simply define all possible conversion methods for zeroes of all numeric types, in the same extension-method way. Obvious, isn''t it?

However, wouldn''t another thing be even simpler? This:

namespace System {
    public static class SystemExtensions {
        public static int IntZero = 0;
        public static uint UIntZero = 0;
        public static Int16 Int16Zero = 0;
        public static UInt16 UInt16Zero = 0;
        public static Int64 Int64Zero = 0;
        public static UInt64 UInt64Zero = 0;
        //...
    } // class SystemExtensions
} // namespace System









更好的是,只需立即使用:





Even better, just the immediate usage:

ulong value = default(ulong); // inspired by Andreas!

[END EDIT]



顺便说一句,即使考虑到这种荒谬的荒谬,我认为这是一个学习真实东西的机会。


谢谢你们这么有趣! :-)



-SA

[END EDIT]

By the way, even considering such an off-the-scale amount of absurdities, I think it as an opportunity to learn something real.

Thank you for so much fun! :-)

—SA


作为使用扩展方法的荒谬的替代方法这个(例如 42.Zero())正如Sergey在解决方案#2中提到的那样,你可以使用 default(T)

例如
As alternative to the the absurdity of employing extension methods for this (e.g. 42.Zero()) as Sergey mentioned in solution #2, you might use default(T).
E.g.
Console.WriteLine("Zero = {0}", default(int));
Console.WriteLine("Zero = {0}", default(DateTime));
Console.WriteLine("Zero = {0}", default(string));



如果你坚持你的名称,您可以将其包装到类中,例如


If you insist in your Zero name, you might wrap it into a class, e.g.

public abstract class Zero
{
    public static T Value<T>() { return default(T); }
}
...
Console.WriteLine("Zero = {0}", Zero.Value<int>());
Console.WriteLine("Zero = {0}", Zero.Value<DateTime>());
Console.WriteLine("Zero = {0}", Zero.Value<string>());



或者如果您更喜欢略有替代的Zero类:


Or if you prefer a slightly alternative Zero class:

public abstract class Zero<T>
{
    public static T Value { get { return default(T); } }
}
...
Console.WriteLine("Zero = {0}", Zero<int>.Value);
Console.WriteLine("Zero = {0}", Zero<DateTime>.Value);
Console.WriteLine("Zero = {0}", Zero<string>.Value);





玩得开心!

干杯

Andi



PS:C#不允许为类型定义扩展方法(例如 Int32.Zero )。您只能在类型的 对象上定义扩展方法(例如 42.Zero())。也许这就是你的困惑。



Have fun!
Cheers
Andi

PS: C# does not allow to define extenstion methods for a type (e.g. Int32.Zero). You only can define extension methods on objects of a type (e.g. 42.Zero()). Maybe this is your confusion.


还有一个基于隐式数字类型转换的变体。让我们考虑一下:

One more variant, based on implicit numeric type conversions. Let''s consider this:
public static class Generic {
    public const byte Zero = 0;
    public const sbyte SignedZero = 0; // will be needed on in one case
} //Generic



显然,与所有其他数字类型一样,排除 sbyte 比字节更宽,它可以工作:


Apparently, as all other numeric types, excluding sbyte are wider then byte, it works:

uint ui = Generic.Zero;
int i = Generic.Zero;
long l = Generic.Zero;
ulong ul = Generic.Zero;
short sh = Generic.Zero;
ushort ush = Generic.Zero;
decimal d = Generic.Zero;
double dbl = Generic.Zero;
Single sng = Generic.Zero;
byte b = Generic.Zero;
// the only special case:
sbyte sb = Generic.SignedZero;



当然只有字节 sbyte 在没有显式转换的情况下不兼容,但所有其他数字类型都兼容 byte sbyte



如果有这样的非对称模式(对 sbyte byte :-))看起来有点难看,另一个选择是在有符号和无符号类型之间平均分配通用常量:


Naturally only byte and sbyte are incompatible without explicit conversion, but all other numeric type are compatible with both byte and sbyte.

If such asymmetric schema (not fair to either sbyte or byte :-)) seems a bit ugly, another option is to distribute the universal constants equally between signed and unsigned types:

public static class Signed {
    public const sbyte Zero = 0;
} // Signed
public static class Unsigned {
    public const byte Zero = 0;
} // Unsigned



在这种情况下,如果所有签名类型(包括两个浮点数)都使用 Signed.Zero ,并且所有无符号类型都使用无符号.Zero ,它会起作用。再次,它看起来有点多余,因为所有类型weider然后 byte sbyte 可以使用任何一种变体。



好​​还是坏?问题是与隐式转换相关的一些性能成本。这是一个运行时操作,因此性能不如使用相同类型的常量或只有立即常量零,这在编译时是已知的。 (在某些语言中,例如Borland Pascal或Deplhi Pascal,有真正的泛型常量。未声明类型,编译器根据目标对象的类型生成实际的立即常量.C和C ++具有#define,这是一个明显的跛脚。)



什么更好?仍然,默认(TYPE)。所有的发明都应该用一些幽默来考虑,即使我们触及编程的严肃方面。







我差点忘了:定义 One 也很好,以确保我们可以完全摆脱任何代码中的所有立即常量。所有其他值都可以显式声明为常量,并放入一些带有定义的特殊文件,甚至放在数据文件和资源中。



另外,好好提一个类似的问题:null应该被认为是可接受的(顺便说一句,上面显示的方案也将涵盖可以为空的数字类型(如 int?)。至于,它应该首先被消灭唯一可接受的选择是 string.Empty



注意解决方案3,因为它显示在其中文本,一次涵盖所有类型,但 string.Empty 仍然需要默认(字符串)当然是null 。



-SA


In this case, if all signed types (including both floating-point) use Signed.Zero, and all unsigned types use Unsigned.Zero, it will work. Again, it looks somewhat redundant, because all types weider then byte and sbyte can use either variant.

Is it good or bad? The problem is some performance cost related to implicit conversion. This is a runtime operation, so the performance will be not as good as with same-type constant or just with immediate constant zero, which are known at compile time. (In some languages, such as Borland Pascal or Deplhi Pascal, there are "real" generic constants. Types are not declared, and the compiler generates real immediate constant depending on the type of target object. C and C++ have "#define", which is an apparent lame.)

What''s better? Still, default(TYPE). All out inventions should be considered with some humor, even though we touch serious aspects of programming.



I almost forgot: it''s also good to have the definition for One, to make sure that we can completely get rid of all immediate constants in any code. All other values can be made explicitly declared constants and put in some special files with definitions, or even in data files and resource.

Also, good to mention one similar issue: null should be considered acceptable (by the way, the scheme shown above will also cover nullable numeric types (like int?). As to "", it should be exterminated first. The only acceptable alternative is string.Empty.

Note that Solution 3, as it is shown in its text, covers all types at once, but string.Empty is still needed as default(string) is of course null.

—SA


这篇关于Int32.Zero的扩展方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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