• 设为首页
  • 点击收藏
  • 手机版
    手机扫一扫访问
    迪恩网络手机版
  • 关注官方公众号
    微信扫一扫关注
    公众号

C#简明教程

原作者: [db:作者] 来自: [db:来源] 收藏 邀请

C#与C++比较概况:

C++ C#
#include <iostream>
using namespace std;
using namespace China::GuangDong::ShenZhen;

namespace China {
    namespace HuBei {
        namespace WuHan {
            class Foo {
                public:
                    static void Func() {
                        cout << "Hello World!" << endl;
                    }
            };
        }
    }
}

 

using System;
using System.IO;
using China.GuangDong.ShenZhen;

namespace China {
    namespace HuBei.WuHan {
        class Foo {
            public static void Func() {
                Console.WriteLine("Hello World!");
            }
        }
    }
}

 

C#具有如下一些特性:

1. C#是强类型语言,所有变量都必须清楚标记为某个特定数据类型

2. C#中基本类型、枚举、结构体为值类型数组、类(stringobject及自定义类)、接口为引用类型

3. 值类型创建在栈上,引用类型创建在托管堆上(由GC来自动管理)

4. 局部变量、out参数变量要在显示初始化赋值后才能访问

5. 成员变量、static成员变量,在没有被显示初始化时,都会被编译器在构造函数或静态构造函数中默认赋初始值,其规则为:值类型为0false,引用类型为null   详见:en

6. 大小写敏感:关键字、宏、变量名、函数名、命名空间名

7. 没有全局变量、没有全局静态变量、没有局部静态变量、没有全局函数,所有东西必须写入结构体或类中

8. 所有类型(含值类型)直接或间接都从object类继承

9. 类单根继承,接口多继承

10. 支持运算符重载(与c++相比,运算符重载函数为public static的)

11. 变量、属性和函数默认为private类型

12. 将程序集添加到工程后,无需显示包含其文件或导入包,带上完整的命名空间即可使用其定义的类型

13. 有构造函数和静态构造函数,没有析构函数,通过引用计数机制进行垃圾回收

14. 成员函数和成员属性默认不是virtual的

 

值类型与引用类型的补充说明:

值类型和引用类型都继承自System.Object类,不同的是,值类型从System.Object的子类System.ValueType继承。

System.ValueType本身是一个类类型,而不是值类型;System.ValueType没有添加任何成员,但覆盖了所继承的一些方法,使其更适合于值类型。

如:System.ValueType重写了Equals()方法,从而对值类型按照实例的值来比较,而不是引用地址来比较。

 

C#预定义基本类型

名称 CTS类型 范围or精度 示例
sbyte System.SByte 8位:-128~127(-2^7~2^7-1)  SByte.MinValue~SByte.MaxValue -123、88、0x1C
short System.Int16 16位:-32768~32767(-2^15~2^15-1)  Int16.MinValue~Int16.MaxValue -123、88、0x1C
int System.Int32 32位:-2147483648~2147483647(-2^31~2^31-1)  Int32.MinValue~Int32.MaxValue -123、88、0x1C
long System.Int64 64位:-9223372036854775808~9223372036854775807(-2^63~2^63-1)  Int64.MinValue~Int64.MaxValue 123L、-123、88、0x1C
byte System.Byte 8位:0~255(0~2^8-1)  Byte.MinValue~Byte.MaxValue 88、0x1C
ushort System.UInt16 16位:0~65536(0~2^16-1)  UInt16.MinValue~UInt16.MaxValue 88、0x1C
uint System.UInt32 32位:0~4294967295(0~2^32-1)  UInt32.MinValue~UInt32.MaxValue 88、0x1C、123U、225u
ulong System.UInt64 64位:0~18446744073709551615(0~2^64-1)  UInt64.MinValue~UInt64.MaxValue 88、0x1C、123UL、225ul
float System.Single 32位单精度浮点数:6~9位有效数字  Single.MinValue~Single.MaxValue -123、88、0x1C、100.0f、-235.68F
double System.Double 64位双精度浮点数:15~17位有效数字  Double.MinValue~Double.MaxValue -123、88、0x1C、320.5、-0.0325
decimal System.Decimal 128位高精度浮点数:28~29位有效数字  Decimal.MinValue~Decimal.MaxValue -123、88、0x1C、-3.0m、25.6M
bool System.Boolean   true、false
char System.Char 16位Unicode字符  Char.MinValue~Char.MaxValue 'c'、'R'、\u0041、\n、'\x0061'

一些用法:

int a = 2;
int a = new int(); // 等价于int a = 0;
int a = default (int);  // 等价于int a = 0;

 

C#预定义引用类型

名称 CTS类型 说明
object System.Object

根类型,CTS中其他类型都是从Object派生而来(包括值类型)

基本方法(派生类可以重写这些方法来实现自己的逻辑):

bool Equals(Object) // 判断两个对象是否相等

int GetHashCode() // 获取当前对象的HashCode(每个对象的HashCode是唯一的)

Type GetType()  // 获取当前对象的类型

string ToString() // 将当前对象转换成string类型

数组 System.Array  
string System.String

Unicode字符串,"Hello World!\n"  ""  "你好" "c:\\1.txt"  @"d:\Music\1.mp3"

"\u6700\u540e\u4fee\u6539\u7684\u7248\u672c:"//最后修改的版本:

Unicode在线转换工具:http://tool.chinaz.com/tools/unicode.aspx

注:在@字符后的所有字符都看成原来的含义,甚至包含换行符(将字符串写成多行时)

字符串虽然是引用类型,但用起来像值类型:原因是string重写了赋值运算符

string s1 = "Hello";
string s2 = s1; // s1、s2都指向"Hello"
s1 = "World"; // s1重新赋值指向"World",s2依然指向"Hello"

 

一些用法:

object o = null;
object o = default(object);

 

基本类型与string间转换

1. 基本类型 --> string,可以调用对应CTS类型中的ToString方法 

2. string --> 基本类型,可以调用对应CTS类型中的Parse和TryParse方法    注:如果string不满足转换要求,Parse方法将会引发一个异常,TryParse方法不会引发异常,它会返回fasle。

 

各类型之间转换

1. 数值基本类型之间隐式转换显示转换

2. 使用Convert类进行基本类型、string、DateTime结构体之间的转换

int i = 10;
float f = i;//f=10

byte b = (byte)i;//b=10

string s1 = "123.5";
f = Convert.ToSingle(s1); //f=123.5

string s2 = "123abc";
i = Convert.ToInt32(s2); //抛出System.FormatException异常

3. 子类对象可以隐式转换为父类对象,父类对象必须显示转换为子类对象(若类型不匹配,则抛出'System.InvalidCastException异常)

4. 值类型可以隐式转换为object类型(装箱),object类型必须显示转换为值类型(类型必须强匹配,int装箱的object只能拆箱成int,不能是long、float等;若类型不匹配,则抛出'System.InvalidCastException异常)

 

checked / unchecked

1. 编译器默认是关闭溢出检查的,建议在测试时开启该checked编译选项

2. checked/unchecked开启/关闭溢出检查  注:若开启了checked溢出检查,运行时发生溢出会抛出OverflowException异常

byte b1 = 255;
int i1 = int.MinValue;
try
{
    checked
    {
        try
        {
            unchecked
            {
                b1++; // 不对b1进行溢出检查
            }
        }
        catch (OverflowException)
        {
            Console.WriteLine("b1 OverflowException.");  // 不会打印该log
        }

        CheckFunc(); // 不会对调用的函数进行溢出检查

        i1--; // 检查发现i1溢出,抛出异常
    }
}
catch (OverflowException)
{
    Console.WriteLine("i1 OverflowException."); // 会打印该log
}

注:checked或者unchecked只影响其包围的语句,不会影响到包围的语句内调用函数

 

is、as运算符

int i1 = 10;
string s1 = "Hello";
object o1 = "Hi";
object o2 = 100;

if (i1 is object) // true
{
    Console.WriteLine("i1 is object");
}

if (s1 is object) // true
{
    Console.WriteLine("s1 is object");
}

if (o2 is string) // false
{
    Console.WriteLine("o2 is string");
}

object i2 = i1 as object; // i1=10被装箱
string s2 = o1 as string; // s2="Hi"
string s3 = o2 as string; // s3=null

 

sizeof

1.只能用于值类型(基本类型、枚举和只包含值类型的结构体)

2.只包含值类型的结构体需要在unsafe块中使用

struct Color
{
    public float R;
    public float G;
    public float B;
    public float A;
}

int i1 = 10;
object i2 = 20;
string s1 = "Hi";

Console.WriteLine(sizeof(int)); //4
//Console.WriteLine(sizeof(i1)); //编译不过
Console.WriteLine(sizeof(double)); //8
Console.WriteLine(sizeof(TimeOfDay));//TimeOfDay枚举类型的size为4

Console.WriteLine(System.Runtime.InteropServices.Marshal.SizeOf(i1)); //4
Console.WriteLine(System.Runtime.InteropServices.Marshal.SizeOf(i2)); //4
//Console.WriteLine(System.Runtime.InteropServices.Marshal.SizeOf(int));//编译不过

unsafe  // 编译设置中需要勾选Allow unsafe code
{
    Console.WriteLine(sizeof(Color)); // 16
}

Console.WriteLine(System.Runtime.InteropServices.Marshal.SizeOf(s1)); //抛异常System.ArgumentException

 

typeof

namespace ConsoleApplication1
{
    enum TimeOfDay
    {
        Moring = -10,
        Afternoon = -11,
        Evenving
    }

    struct Color
    {
        public float R;
        public float G;
        public float B;
        public float A;
    }
}

Type t1 = typeof(TimeOfDay);
Type t2 = typeof(Color);

Console.WriteLine(t1);//ConsoleApplication1.TimeOfDay
Console.WriteLine(t2);//ConsoleApplication1.Color

Console.WriteLine(typeof(int));//System.Int32
Console.WriteLine(typeof(string));//System.String

 

可空类型?  派生于结构体Nullable<T>

1. 可空类型与其他可空类型之间的转换,遵循非可空类型的转换规则:如:int?可隐式转换为long?、float?、double?和decimal?

2. 非可空类型与其他可空类型之间的转换,遵循非可空类型的转换规则:如:int可隐式转换为long?、float?、double?和decimal?

3. 可空类型必须显示地转换为非可空类型(若可空类型为null,转换时抛System.InvalidOperationException异常)

4. 可空类型与一元或二元运算符一起使用时,如果其中一个操作数或两个操作数都是null,其结果就是null

int? a = null;
int? b = a + 1;//b=null
int? c = a * 2;//c=null

int? d = 3;//d=3

//比较的2个数中只要有一个为空类型则为false
if (a >= d)
{
    Console.WriteLine("a>=d");
}
else if (a < d)
{
    Console.WriteLine("a<d");
}
else
{
    Console.WriteLine("Oh, My God!");//该行被打印
}

 

空合并运算符??

1. 空合并运算符:若第一个操作数不是null,表达式为第一个操作数的值;若第一个操作数为null,则表达式为第二个操作数的值

int? a = null;
int? b = 3;//b=3

int c = a ?? 4;//a为空类型,则把??后面的数4赋值给c
int d = b ?? 5;//b不为空类型,则把b赋值给d

 

空条件运算符?.和?[]  【c#6.0】

1. 实例在访问成员或数组访问元素前自动判空,不用显示添加手动判空代码,让程序更优雅

int? len = customers?.Length; //null if customers is null   等价于int? len = (customers==null?null:customers.Length)
Customer first = customers?[0];  // // null if customers or customers[0] is null 等价于Customer first = (customers==null?null:(customers.Length==0?null:customers[0]))
int? count = customers?[0]?.Orders?.Count();  // 等价于int? count = (customers==null?null:(customers.Length==0?null:(customers[0]==null?null:(customers[0].Orders==null?null:customers[0].Orders.Count))))

 

条件语句

1. swith case可以把字符串当作测试变量

switch (country)
{
      case "China":
            break;
      case "America":
            break;
      default:
            break;
}

 

循环语句

1. foreach循环

foreach (int n in arrayOfInts)
{
    Console.WriteLine(n);
}

 

命名空间别名

除了C#与C++比较概况中提到的命名空间的用法外,C#还允许使用别名来简化类型对命名空间的使用(注:通过::符号来使用)

using System;
using InterSrv = System.Runtime.InteropServices;

byte a = 3;
int nLen = InterSrv::Marshal.SizeOf(a.GetType());
Console.WriteLine("Type is {0}, Length is {1}.", a.GetType().ToString(), nLen); // Type is System.Byte, Length is 1.

 

函数参数传递  【ref  out】

int a1 = 1, b1 = 2;
Func(a1, b1);//函数返回后,a1=1 b1=2

int a2 = 1, b2 = 2;
FuncRef(ref a2, ref b2);//函数返回后,a2=2 b2=1

int a3 = 1;//由于out参数不会使用该初值,因此a3可以不用赋初值
FuncOut(out a3);//函数返回后,a3=5

CA oa1 = null;
Func2(oa1);//函数返回后,oa1=null

CA oa2 = null;
FuncRef2(ref oa2);//函数返回后,oa2不为null,oa2.Id=100

CA oa3 = new CA();//由于out参数不会使用该初值,因此oa3可以不用赋初值
FuncOut2(out oa3);//函数返回后,oa3=null

void Func(int a, int b)
{
    int c = a;
    a = b;
    b = c;
}

void FuncRef(ref int a, ref int b)
{
    int c = a;
    a = b;
    b = c;
}

void FuncOut(out int a)
{
    //int b = a; //在函数中未给out参数变量a赋值之前,不能访问a
    a = 5;//在函数返回之前必须要对a进行赋值
}

void Func2(CA o)
{
    o = new CA();
    o.Id = 100;
}

void FuncRef2(ref CA o)
{
    o = new CA();
    o.Id = 100;
}

void FuncOut2(out CA o)
{
    //bool b = (o != null);//在函数中未给out参数变量o赋值之前,不能访问o
    o = null;//在函数返回之前必须要对o进行赋值
}

 

命名参数  【c#4.0】

string s = GetFullName(LastName: "Li", FirstName: "Lei");

string GetFullName(string FirstName, string LastName)
{
    return FirstName + " " + LastName;
}

 

缺省参数  【c#4.0】

string GetFullName(string FirstName, string LastName="Chen")
{
    return FirstName + " " + LastName;
}

 

数组型参数

params会把传入各个参数存放在一个object数组中

1.params参数必须放在最后
2.函数只允许有一个params参数

public static void Test(int n, params object[] list)
{
    Console.WriteLine(n);

    for (int i = 0; i < list.Length; i++)
    {
        Console.WriteLine(list[i]);
    }
}

Test(100, false, 3, "Test");//打印出:100 False 3 Test

 

类型推断  【c#3.0】

1.推断出了类型后,就不能改变类型了

2.类型确定后,就遵循强类型化规则

var name = "Jim Green";
var age = 20;
var height = 1.825f;
var sex = true;

//var weight; 编译不过,必须在声明时初始化
//weight = 60.5;

Console.WriteLine("name's type is {0}", name.GetType());//name's type is System.String
Console.WriteLine("age's type is {0}", age.GetType());//age's type is System.Int32
Console.WriteLine("height's type is {0}", height.GetType());//height's type is System.Single
Console.WriteLine("sex's type is {0}", sex.GetType());//sex's type is System.Boolean

Object o = new Object();
var o1 = new Object();
var o2 = o;

//var friend = null;编译不过,不能为空

 

匿名类型

var与关键字new一起使用可以创建匿名类型;匿名类型只是一个从Object派生没有名称的类,该类的定义从初始化器中推断

匿名类型名有编译器按照一定规则产生,我们不应该使用任何该类型的反射

//生成一个包含string FirstName, string MiddleName, string LastName属性的类型,并用该类型初始化出个名为captain的实例
var captain = new { FirstName = "James", MiddleName = "T", LastName = "Kirk" };
//生成一个包含string Location, int Area, double Population属性的类型,并用该类型初始化出个名为china的实例
var china = new { Location = "Asia", Area = 960, Population = 1.3 };
// doctor与captain的变量名、类型、顺序完全一致,为同一匿名类型;因此,不会创建新的类型,而是使用captain类型来初始化captain
var doctor = new { FirstName = "Leonard", MiddleName = "T", LastName = "McCoy" };

Console.WriteLine("captain's type is {0}", captain.GetType());//captain's type is <>f__AnonymousType0`3[System.String,System.String,System.String]
Console.WriteLine("china's type is {0}", china.GetType());//china's type is <>f__AnonymousType1`3[System.String,System.Int32,System.Double]
Console.WriteLine("doctor's type is {0}", doctor.GetType());//doctor's type is <>f__AnonymousType0`3[System.String,System.String,System.String]

 

格式化输出到控制台

格式符形如:{D[,D[:C[D]]]}  -- DDD表示数字,C表示字母

D:后续参数序号,从0开始

D:占位数目(占位数少于变量自身数目时,不产生多余占位;货币符号算1个占位):为正数,表示右对齐;为负数,表示左对齐

D:整型数时,为整个数的位数,不够时左边补0;浮点数时,为小数点后的位数

C:① D -- 十进制格式

      ② E、e -- 科学计数法,默认小数点后的位数为6

      ③ F -- 浮点数格式

      ④ G -- 普通格式

      ⑤ N -- 数字格式,逗号表示千位符

      ⑥ P -- 百分数格式

      ⑦ X -- 十六进制格式

      ⑧ C -- 本地货币格式  中国区为:¥

int i = 262, j = 350;
Console.WriteLine("{0}#{1}", i, j);//262#350
Console.WriteLine("{0,4}#{1,5}", i, j);// 262#  350
Console.WriteLine("{0,-4}#{1}", i, j);//262 #350
Console.WriteLine("{0,6:D5}#{1}", i, j);// 00262#350

int m = 26252, n = 350390;
Console.WriteLine("{0,0:D}#{1,0:F}", m, n);//26252#350390.00
Console.WriteLine("{0,0:G}#{1,0:N}", m, n);//26252#350,390.00
Console.WriteLine("{0,0:E}#{1,0:e}", m, n);//2.625200E+004#3.503900e+005
Console.WriteLine("{0,0:X}#{1,0:P}", m, n);//668C#35,039,000.00%

float f = 35.0f, g = -20.388f;
Console.WriteLine("{0,7:F3}#{1,0:E2}", f, g);// 35.000#-2.04E+001
Console.WriteLine("{0,4:C2}#{1,0:e3}", f, g);//¥35.00#-2.039e+001
Console.WriteLine("{0,6:C1}#{1,0:P3}", f, g);// ¥35.0#-2,038.800%

 

字符串(16位unicode)

String处理不变的字符串,,不可被继承(sealed),任何对String的改变都会引发新的String对象的生成

string s0 = "你好";
int ns0Len = s0.Length; // ns0Len = 2

char[] sz = new char[] { 'h', 'e', 'l', 'l', 'o' };

string s1 = "hello";        // 静态创建字符串对象
string s2 = new string(sz); 
                      

鲜花

握手

雷人

路过

鸡蛋
该文章已有0人参与评论

请发表评论

全部评论

专题导读
上一篇:
Cstatic关键字理解发布时间:2022-07-13
下一篇:
C#访问修饰符及各种元素的访问修饰符的默认值发布时间:2022-07-13
热门推荐
阅读排行榜

扫描微信二维码

查看手机版网站

随时了解更新最新资讯

139-2527-9053

在线客服(服务时间 9:00~18:00)

在线QQ客服
地址:深圳市南山区西丽大学城创智工业园
电邮:jeky_zhao#qq.com
移动电话:139-2527-9053

Powered by 互联科技 X3.4© 2001-2213 极客世界.|Sitemap