C# 教程 在线

2391C# 枚举(Enum)

枚举列表中的每个符号代表一个整数值,一个比它前面的符号大的整数值。默认情况下,第一个枚举符号的值是 0。

但是,你也可以自定义每个符号的值:

using System;
namespace EnumApplication
{
    class EnumProgram
    {
        enum Days {
            Mon=71, 
            tue=61, 
            Wed=51, 
            thu=41, 
            Fri=51, 
            Sat=61, 
            Sun=71
        };

        static void Main(string[] args)
        {
            int WeekdayStart = (int)Days.Mon;
            int WeekdayEnd = (int)Days.Fri;
            Console.WriteLine("Monday: {0}", WeekdayStart);
            Console.WriteLine("Friday: {0}", WeekdayEnd);
            Console.ReadKey();
        }
    }
}

输出结果:

Monday: 71
Friday: 51

2390C# 结构体(Struct)

C# 中结构类型和类类型在语法上非常相似,他们都是一种数据结构,都可以包括数据成员和方法成员。

结构和类的区别:

  • 1、结构是值类型,它在栈中分配空间;而类是引用类型,它在堆中分配空间,栈中保存的只是引用。
  • 2、结构类型直接存储成员数据,让其他类的数据位于堆中,位于栈中的变量保存的是指向堆中数据对象的引用。

C# 中的简单类型,如int、double、bool等都是结构类型。如果需要的话,甚至可以使用结构类型结合运算符运算重载,再为 C# 语言创建出一种新的值类型来。

由于结构是值类型,并且直接存储数据,因此在一个对象的主要成员为数据且数据量不大的情况下,使用结构会带来更好的性能。

因为结构是值类型,因此在为结构分配内存,或者当结构超出了作用域被删除时,性能会非常好,因为他们将内联或者保存在堆栈中。当把一个结构类型的变量赋值给另一个结构时,对性能的影响取决于结构的大小,如果结构的数据成员非常多而且复杂,就会造成损失,接下来使用一段代码来说明这个问题。

结构和类的适用场合分析:

  • 1、当堆栈的空间很有限,且有大量的逻辑对象时,创建类要比创建结构好一些;
  • 2、对于点、矩形和颜色这样的轻量对象,假如要声明一个含有许多个颜色对象的数组,则CLR需要为每个对象分配内存,在这种情况下,使用结构的成本较低;
  • 3、在表现抽象和多级别的对象层次时,类是最好的选择,因为结构不支持继承。
  • 4、大多数情况下,目标类型只是含有一些数据,或者以数据为主。

2389C# 结构体(Struct)

补充:类与结构体的区别

1、结构体中声明的字段无法赋予初值,类可以:

struct test001
{
    private int aa = 1;
}

执行以上代码将出现“结构中不能实例属性或字段初始值设定”的报错,而类中无此限制,代码如下:

class test002
{
    private int aa = 1;
}

2、结构体的构造函数中,必须为结构体所有字段赋值,类的构造函数无此限制:

补充:类与结构的选择

首先明确,类的对象是存储在堆空间中,结构存储在栈中。堆空间大,但访问速度较慢,栈空间小,访问速度相对更快。故而,当我们描述一个轻量级对象的时候,结构可提高效率,成本更低。当然,这也得从需求出发,假如我们在传值的时候希望传递的是对象的引用地址而不是对象的拷贝,就应该使用类了。

2388C# 字符串(String)

C# string.Format格式化日期

DateTime dt = new DateTime(2017,4,1,13,16,32,108);
string.Format("{0:y yy yyy yyyy}",dt); //17 17 2017 2017
string.Format("{0:M MM MMM MMMM}", dt);//4  04 四月 四月
string.Format("{0:d dd ddd dddd}", dt);//1  01 周六 星期六
string.Format("{0:t tt}", dt);//下 下午
string.Format("{0:H HH}", dt);//13 13
string.Format("{0:h hh}", dt);//1  01
string.Format("{0:m mm}", dt);//16 16
string.Format("{0:s ss}", dt);//32 32
string.Format("{0:F FF FFF FFFF FFFFF FFFFFF FFFFFFF}", dt);//1 1  108 108  108   108    108
string.Format("{0:f ff fff ffff fffff ffffff fffffff}", dt);//1 10 108 1080 10800 108000 1080000
string.Format("{0:z zz zzz}", dt);//+8 +08 +08:00

string.Format("{0:yyyy/MM/dd HH:mm:ss.fff}",dt);  //2017/04/01 13:16:32.108
string.Format("{0:yyyy/MM/dd dddd}", dt);      //2017/04/01 星期六
string.Format("{0:yyyy/MM/dd dddd tt hh:mm}", dt); //2017/04/01 星期六 下午 01:16
string.Format("{0:yyyyMMdd}", dt);         //20170401
string.Format("{0:yyyy-MM-dd HH:mm:ss.fff}", dt); //2017-04-01 13:16:32.108

除去string.Format()可以对日期进行格式化之外,*.ToString()也可以实现相同的效果:

DateTime dt = new DateTime(2017,4,1,13,16,32,108);
dt.ToString("y yy yyy yyyy");//17 17 2017 2017
dt.ToString("M MM MMM MMMM");//4  04 四月 四月
dt.ToString("d dd ddd dddd");//1  01 周六 星期六
dt.ToString("t tt");//下 下午
dt.ToString("H HH");//13 13
dt.ToString("h hh");//1  01
dt.ToString("m mm");//16 16
dt.ToString("s ss");//32 32
dt.ToString("F FF FFF FFFF FFFFF FFFFFF FFFFFFF");//1 1  108 108  108   108    108
dt.ToString("f ff fff ffff fffff ffffff fffffff");//1 10 108 1080 10800 108000 1080000
dt.ToString("z zz zzz");//+8 +08 +08:00

dt.ToString("yyyy/MM/dd HH:mm:ss.fff"); //2017/04/01 13:16:32.108
dt.ToString("yyyy/MM/dd dddd");      //2017/04/01 星期六
dt.ToString("yyyy/MM/dd dddd tt hh:mm"); //2017/04/01 星期六 下午 01:16
dt.ToString("yyyyMMdd");         //20170401
dt.ToString("yyyy-MM-dd HH:mm:ss.fff"); //2017-04-01 13:16:32.108

2387C# 方法

对于复杂引用类型参数传递的控制

所谓复杂,是参数是数组或集合类型,或者参数包含这些类型数据,这种情况下上面的方法不能保证参数数据不被修改,因为即使对象为只读的,但是对象中的数组或集合字段(属性)还是可以修改的。

1、集合参数(包含集合字段的引用参数也一样)

.net 4.5以前版本可以使用不包含修改集合元素方法的接口来代替具体集合类型。例如使用IEnumerable<T>接口代替List<T>。4.5版本可以直接使用IReadOnlyCollection接口或实现该接口的集合类型。

2、数组参数

没有好的办法保护数组类型参数不被修改,所以尽量避免使用数组类型作为方法参数,除非用到可选参数时候。

更多内容参考:C# 中数组作为参数传递的问题