当前位置:威尼斯 > 编程 > 声明为其他类型如Int16、Int32、Int64等都不行,模

声明为其他类型如Int16、Int32、Int64等都不行,模

文章作者:编程 上传时间:2019-09-29

1、枚举定义证明基础项指标界定

想要定义三个意味着数据库主键编号范围的枚举:

    /// <summary>    /// 编号范围枚举    /// </summary>    public enum IDRangeType : Int64    {        /// <summary>        /// 1到2的32次方        /// </summary>        [Description("1到2的32次方")]        Between1ToPowerOf32 = 2147483748,        /// <summary>        /// 2的32次方到2的40次方        /// </summary>        [Description("2的32次方到2的40次方")]        BetweenPowerOf32ToPowerOf40 = 2199023255552,        /// <summary>        /// 2的40次方以上        /// </summary>        [Description("2的40次方以上")]        Bigger = Int64.MaxValue,    }

而是下面这种注明直接产生编写翻译错误:应输入类型 byte、sbyte、short、ushort、int、uint、long 或 ulong

也便是说,枚举的根底项目只可以为8种数字类型: byte、sbyte、short、ushort、int、uint、long 或 ulong。证明为别的品种如Int16、Int32、Int64等都出色。

遵照VS编写翻译指示,将Int64改为long,果然通过,真是奇哉怪也。

咱俩一直晓得的Int64和long其实在MS .Net Framework中是从没有过差别的,long只是Int64的四个别称而已(而Java的基元值类型的包裹类都以引用类型),况且Framework编制程序典型里还明白说推荐应用Int64,那样能够保障跨语言只怕跨平台代码移植方便。但是在枚举声明这里,只好使用外号。

附带再提一下.NET Framework中国和欧洲常极其的三个档期的顺序System.Enum,它是个援引类型,Framework中将System.Enum定义为多个抽象类,可是它又继续自System.ValueType。

因此项目判别,却又发掘它不是ValueType,并且亦不是枚举:

            var num = new Int32();            Console.WriteLine(num is ValueType); //True            Console.WriteLine(num.GetType().IsValueType); //True            var type = typeof(System.Enum);            Console.WriteLine(type.IsValueType); //False ???            Console.WriteLine(type.IsEnum); //False ???

C#语言特征中有多数特例存在,System.Enum即为一例。

枚举类型概述

枚举类型使用 enum 关键字注脚。是值类型,但不可能定义任何方法、属性、事件。(PS. 能够行使“扩大方法”模拟向枚举类型增加方法)

各类枚举类型都从 System.Enum 派生,后者从 System.ValueType 派生,而 System.ValueTypeSystem.Object 派生。

枚举类型定义的号子是常量值,在编写翻译时,会用对应的数值替换援引了枚举类型的暗记。那意味运营时恐怕没有需求定义了枚举类型的主次集。

在营造系统的时候,成立一组符号名来对应已知的数值会很有利,举例,以下 Days 类型定义了一组符号,每一个符号都标志十三日中的一天。 该变量只好存款和储蓄八个有意义的值:

internal enum Days
{
    Sunday,     // 星期天
    Monday,     // 星期一
    Tuesday,    // 星期二
    Wednesday,  // 星期三
    Thursday,   // 星期四
    Friday,     // 星期五
    Saturday    // 星期六
}

默许意况下,第四个元素的值会设置为 0 ,别的的根据 n+1 递推。依据供给,大家也得以改换第三个成分的启幕值,如:

internal enum Days
{
    Sunday = 101,   // 星期天
    Monday,         // 星期一  = 102
    Tuesday,        // 星期二  = 103
    Wednesday,      // 星期三  = 104
    Thursday,       // 星期四  = 105
    Friday,         // 星期五  = 106
    Saturday        // 星期六  = 107
}

枚举值也不必然是连连的,如:

internal enum Days
{
    Sunday = 107,     // 星期天
    Monday = 101,     // 星期一
    Tuesday = 109,    // 星期二
    Wednesday = 108,  // 星期三
    Thursday = 106,   // 星期四
    Friday = 102,     // 星期五
    Saturday = 105    // 星期六
}

用来保存枚举值的储存类型默许是 int,我们也能够改成别的基元类型(byte, sbyte, short, ushort, uint, long, ulong)。如将 Days 枚举类型的骨子里存款和储蓄值设置为 byte ,能够如此写:

internal enum Days : byte
{
    Sunday,     // 星期天
    Monday,     // 星期一
    Tuesday,    // 星期二
    Wednesday,  // 星期三
    Thursday,   // 星期四
    Friday,     // 星期五
    Saturday    // 星期六
}

那般做的补益是能够节外省部存款和储蓄器,但要注意每三个值必得在其范围内。C#编写翻译器为了简化本人的落到实处,供给只好钦命基元类型名称,假诺钦命 Int32,会彰显以下错误音讯:

应输入类型 byte、sbyte、short、ushort、int、uint、long 或 ulong

一、枚举类型
  枚举类型(enumerated types)定义了一组"符号名称/值"配成对。
  比方,以下Color类型定义了一组符号,每一个符号都标记一种颜色:

2、web服务的顾客端代理和服务端的枚举数值定义分歧样

还以上边包车型大巴枚举作为示范,大家要在一个标志为WebMethod的web服务议程中应用这几个枚举,新建一个web服务并安插好之后供顾客端调用。

经过WSDL工具,直接将这些web服务浮动保存为本地代理类,然后查看代理类源代码,客商端代理类生成的枚举IDRangeType竟然产生:

    public enum IDRangeType : long    {        Between1ToPowerOf32,        BetweenPowerOf32ToPowerOf40,        Bigger,    }

客户端生成的枚举,未有把服务端枚举定义中显式定义的数值带过来。对于IDRangeType这种定义枚举就是要使用枚举的数值来说,几乎太出乎人的预料之外。

下一场想到或者是连串化和反类别化的标题,尝试着给枚举属性分别增加性情DataMember和EnumMember,难题照旧。但在WCF试验中发掘一切寻常,展开WCF生成的客商端代理类,枚举数值的概念和服务端没什么变化。

新兴心想又搞不知道,枚举既然是承继自基元值类型,那么值类型怎么体系化,枚举也应当像基元值类型同样连串化才对,况兼向来讲服务分享Schema(for structures) 和 Contract(for behaviors), 实际不是Class,难道枚举不是Schema和Contract的一有个别,或然是SOAP的.NET达成不补助枚举?

考试数次持久不能一举成功难点,最后寻觅一下.net web服务和枚举那四个重大字,发掘果然很已经有一篇流传甚广的Web Services and C# Enums文章讲到“Numeric Values Are Not Preserved”那些业务。文章还会有涉及,在web服务中,Flag标识下的枚举在客商端生成的时候数值改换,很轻巧导致不幸后果(This can lead to disastrous consequences)。

通过这些主题素材,让本人深暗意识到服务端和顾客端生成代码的距离,不相同情形分歧应用场景下,有个别非常情状很轻巧偏离习贯认识和无理决断,必需多品尝举办本领出真知。

参考:

枚举类型的补益

实际,在事实上行使中咱们也可以运用 0 表示 星期天1 表示 星期一,依此类推,如下:

public const int Sunday = 0;
public const int Monday = 1;
public const int Tuesday = 2;
public const int Wednesday = 3;
public const int Thursday = 4;
public const int Friday = 5;
public const int Saturday = 6;

唯独,使用枚举类型而不采纳数值类型有以下好处:

  • 枚举类型使代码变得更易于编写、阅读和保证,在 Visual Studio 中,速龙liSense 能向开辟者展现有含义的号子名称,开荒者不用费心去记住每一个数值代表的意思;
  • 枚举类型是强类型,明显钦点哪些值是变量的有效值。
internal enum Color {
While,        //赋值0
Red,          //赋值1
Green,        //赋值2
Blue,         //赋值3
Orange        //赋值4
}

  使用枚举类型的功利:  

威尼斯,  1)枚举类型使程序更便于编写、阅读和掩护。有了枚举类型,符号名称可在代码中不管采纳,开垦职员没有须求记 住每个硬编码的意义。並且,一旦与符号名称对应的值产生变化,代码也得以轻松的再次编写翻译,没有供给对源代码做出别的修改。除了这些之外,文书档案工具和别的实用程序能向开垦职员显示有含义的号子名称。

  2)枚举类型是强类型的。

  在Microsoft .NET Framework中,枚举类型不只是编译器所关注的标记,它在档期的顺序系统中还怀有"一等公民"的地 位,能完毕丰裕强大的操作。枚举类型都一向从System.Enum派生,后面一个从System.ValueType派生,而System.ValueType用从 System.Object派生。所以,枚举类型是值类型,可代表成未装箱和已装箱格局。可是,有别于其余值类型,枚 举类型不可能定义任何措施、属性和事件。但是可应用C#的"扩张方法"效用模拟向枚举类型增加方法。

  编写翻译枚举类型时,C#编写翻译器会把各类符号转变到为门类的二个常量字段。比方,编译器会把前面包车型地铁Color枚举类型看成以下代码:

internal struct Color : System.Enum
{
  //以下是一些公共常量,它们定义了Color的符号和值
  public const Color While = (Color)0;
  public const Color Red = (Color)1;
  public const Color Green = (Color)2;
  public const Color Bule = (Color)3;
  public const Color Orange = (Color)4;

  //以下是一个公共实例字段,它包含一个Color变量的值,
  //不能写代码来直接引用这个实例字段
  public Int32 value__;
}

  C#编写翻译器实际上并不编写翻译这段代码,因为它取缔定义从System.Enum这一特别类型派生的品类。可是,能够透过 上述伪类型定义明白其西藏中华工程公司作办法。简单来说,枚举类型只是三个结构,在那之中定义了一组常量字段和三个实例字 段。常量字段会嵌入程序集的元数据中,并能够透过反射来访谈。那意味能够在运转时收获与枚举类型关联的 全数符号及其值。还意味着能够将二个字符串符号调换来对应的数值。这个操作是透过System.Enum基类型来提 供的,该品种提供了几个静态和实例方法,可选拔它们操作枚举类型的三个实例,从而幸免了必须利用反射的麻 

烦。  

  提醒:枚举类型定义的标记是常量值。所以当编写翻译器开掘代码援用了多个枚举类型的符号,就能在编写翻译时用数值 替换符号,代码将不再援引定义了符号的枚举类型。那代表在运营时大概无需定义了枚举类型的程序集,在 

编写翻译时须求。

  比如,System.Enum类型有八个GetUnderlyingType的静态方法,而System.Type类型有一个 GetEnumUnderlyingType的实例方法。

public static Type GetUnderlyingType (Type enumType); //System.Enum中定义
public Type GetEnumUnderlyingType (Type enumType); //System.Type中定义

  那几个格局重回用于容纳二个枚举类型的值的基础项目。每一个枚举类型皆有八个基础项目,它可以是byte,sbyte, short,ushort,int(最常用,也是C#暗中同意的),uint,long,或ulong。纵然这一个C#基元类型都有都有指标的FCL 类型,但C#编写翻译器为了简化自个儿的落到实处,供给只可以钦定基元类型名称。如若运用FCL类型名称(如Int32),就能报 

错。
  以下代码演示了什么声美素佳儿(Friso)个基础项目为byte(System.Byte)的枚举类型:

inter enum Color :byte {
    While, 
    Red, 
    Green, 
    Blue, 
    Orange 
}

  基于这些Color枚举类型,一下代码展现了GetUnderlyingType 的回来结果:

//以下代码会显示"System.Byte"
Console.WriteLine(Enum.GetUnderlyingType(typeof(Color)));

  C#编写翻译器将枚举类型视为基元类型。所以,能够行使过多操作符(==,!=,<,>等等)来操作枚举类型的实例。 全部那些操作符实际成效于枚举类型实例之中的value__实例字段。别的,C#编写翻译器还运转将枚举类型的实例显式 的转型为三个不通过的枚举类型。也足以显式将贰个枚举类型实例转型为二个数值类型。

  能够调用System.Enum的静态方法GetValue可能System.Type的实例方法GetEnumValue获取二个数组,该数组的每二个因素都对应枚举类型中的一个符号名称,每种成分都满含符号名称的数值:

public static Array GetValues(Type enumType); //System.Enum中定义
public Array GetEnumValues(Type enumType); //System.Type中定义

  这几个艺术结合ToString方法应用,可展现枚举类型中具备符号名称及其相应的数值,如下所示:

public static void Go() {
    Color[] colors = (Color[])Enum.GetValues(typeof(Color));
    Console.WriteLine("Number of symbols defined: " + colors.Length);
    Console.WriteLine("ValuetSymboln-----t------");
    foreach (Color color in colors) {
  // 以十进制和常规格式显示每个符号
    Console.WriteLine("{0,5:D}t{0:G}", color);
    }
}

  以上代码发生的出口如下:

Number of symbols defined: 5
Value Symbol


0 While
1 Red
2 Green
3 Blue
4 Orange

  还也可以有其它枚举类型成员,就不一一呈报了!

二、位标志
  程序员平日要与位标志(bit flag)群集打交道。调用System.IO.File类型的GetAttributes方法,会再次来到FileAttributes类型的四个实例。FileAttributes类型是宗旨项目为Int32的枚举类型,在那之中每种人都呈现了文件的一项属性。FileAttibutes类型在FCL中的定义如下:

[Flags]
[Serializable]
[ComVisible (true)]
public enum FileAttributes
{
    Archive = 0x00020,
    Compressed = 0x00800, 
    Device = 0x00040, 
    // Reserved for future use (NOT the w32 value). 
    Directory = 0x00010,
    Encrypted = 0x04000, // NOT the w32 value
    Hidden = 0x00002,
    Normal = 0x00080,
    NotContentIndexed = 0x02000,
    Offline = 0x01000,
    ReadOnly = 0x00001,
    ReparsePoint = 0x00400,
    SparseFile = 0x00200,
    System = 0x00004,
    Temporary = 0x00100,
    #if NET_4_5
    IntegrityStream = 0x8000,
    NoScrubData = 0x20000,
    #endif
}

  为了认清一个文件是不是隐身,可举行上边那样的代码:

String file = Assembly.GetEntryAssembly().Location;
FileAttributes attributes = File.GetAttributes(file);
Console.WriteLine("Is {0} hidden? {1}",file,(attributes & FileAttributes.Hidden) !=0);

  以下代码演示了什么样将三个文书的质量改为只读和隐形:

File.SetAttributes(file,FileAttributes.ReadOnly | FileAttribute.Hidden);

  正如FileAttributes类型呈现的那么,平日都要用枚举类型来表示一组能够结合的位标记。可是,尽管枚举类型和位标记相似,但它们的语义不尽一样。举个例子,枚举类型表示单个数值,而位标志表示一组位,其中多少位是1,有 些位是0.

  定义用于标识位标记的枚举类型时,当然应该显式为每一种符号分配多个数值。常常,各类符号都有单独的贰个位处于on(1)状态.别的,常常都要定义二个值为0的None符号。仍可以定义一些意味常用位构成的暗记。其余,刚毅建议向枚举类型应用System.Flags.Attribute这一个定制的attribute类型,如下所示

[Flags] 
public enum Actions {
    Read = 0x0001,
    Write = 0x0002,
    ReadWrite = Actions.Read | Actions.Write,
    Delete = 0x0004,
    Query = 0x0008,
    Sync = 0x0010
}

  因为Actions是枚举类型,所以在操作位标记枚举类型时,能够运用上一节陈诉的保有办法。

Actions actions = Actions.Read | Actions.Delete; //0x0005
Console.WriteLine(actions.ToString()); //"Read,Delete"

  调用ToString时,它会视图将数值调换为相应的标志。今后的数值是0x0005,它并未有对应的标识。但是,ToString方法检查实验到Actions类型上存在[Flags]其一attribute,所以ToString方法今后不会将该数值视为单独的值。相反,会将它正是一组位标记。由于0x0005有0x0001和0x0004组合而成,所以ToString会生成字符串"Read,Delete", 即便从Actions类型中除去[Flags]那一个attribute,ToString方法再次来到"5"。

  长久不要对位标识枚举类型使用IsDefined方法,理由如下:
  1)假如向IsDefined方法传递多少个字符串,它不会将那一个字符串拆分为独立的token来打开检索,而是视图查找整个字符串,把它作为是包涵逗号的二个更加大的暗号。由于无法在枚举类型中定义含有逗号的符号,所以这几个标志长久找不到。
  2)如若向IsDefined方法传递三个数值,它会检查枚举类型是还是不是定义了二个其对应数值和传颂数值相称的暗号。由于位标识无法这么总结相称,所以IsDefined平日会重临flase。

三、向枚举类型增添方法
  将来,能够使用C#的扩大方法效果向枚举类型模拟加多方法。
  假使想为FileAttributes枚举类型丰盛一些办法,能够定义叁个含有了扩展方法的静态类,如下所示:

public static Boolean Set(this FileAttributes flags, FileAttributes testFlags) {
return flags | testFlags;
}

  从外表看,我仿佛的确在枚举类型上调用这一个艺术:

FileAttributes fa = FileAttributes.System;
fa = fa.Set(FileAttributes.ReadOnly);

 

本文由威尼斯发布于编程,转载请注明出处:声明为其他类型如Int16、Int32、Int64等都不行,模

关键词: