C# 基本概念、数据类型、运算符、语句

C# 是一种面向对象的语言,还进一步支持面向组件的编程。
C# 采用统一的类型系统。 所有 C# 类型(包括 int 和 double 等基元类型)均继承自一个根 object 类型。
C# 语言忽略缩进和空格,因此;是必须的(除了方法和访问器块之后不需要;)。


一个简单的HelloWorld

此类的完全限定的名称为HelloWorldApplication .HelloWorld

using System;//引用外部命名空间
namespace HelloWorldApplication //声明自身命名空间
{
   class HelloWorld
   {
      static void Main(string[] args) //声明Main方法,这是所有C#程序的入口
      {
         /* 我的第一个 C# 程序*/
         Console.WriteLine("Hello World");
         Console.ReadKey();//等待按键,防止运行结束后程序关闭
      }
   }
}
  • 在任何 C# 程序中的第一条语句都是:
    using System;
    通过using 关键字引用命名空间,即可使用其中包含的公共类型和成员。
  • 标识符
    标识符必须以字母、下划线或 @ 开头,不能含有$,不能与关键字或C#的类库名称相同

数据类型

C# 有两种类型:值类型和引用类型。 值类型的变量直接包含数据,而引用类型的变量则存储对数据(称为“对象”)的引用。 对于引用类型,两个变量可以引用同一对象;因此,对一个变量执行的运算可能会影响另一个变量引用的对象。 借助值类型,每个变量都有自己的数据副本;因此,对一个变量执行的运算不会影响另一个变量(refout 参数变量除外)。

值类型

所有值类型均隐式继承自 ValueType,后者又隐式继承自 object

  • [简单类型]
    • 有符号的整型:sbyteshortintlong
    • 无符号的整型:byteushortuintulong
    • Unicode 字符:char
    • IEEE 二进制浮点:floatdouble
    • 高精度十进制浮点数:decimal (用于财务计算。可以通过在一个浮点类型的值后加Mm声明。)
    • 布尔:bool
  • [枚举类型]
    • 格式为 enum E {...} 的用户定义类型
  • [结构类型]
    • 格式为 struct S {...} 的用户定义类型
  • [可以为 null 的值类型]
    • 值为 null 的其他所有值类型的扩展

引用类型

  • [类类型]
    • 其他所有类型的最终基类:object
    • Unicode 字符串:string
    • 格式为 class C {...} 的用户定义类型
  • [接口类型]
    • 格式为 interface I {...} 的用户定义类型
  • [数组类型]
    • 一维和多维,例如 int[]int[,]
  • [委托类型]
    • 格式为 delegate int D(...) 的用户定义类型
对象(Object)类型

是所有数据类型的终极基类ObjectSystem.Object 类的别名。对象类型可以被分配任何其他类型(值类型、引用类型、预定义类型或用户自定义类型)的值。
在分配值之前,需要先进行类型转换。当一个值类型转换为对象类型时,则被称为 装箱;另一方面,当一个对象类型转换为值类型时,则被称为 拆箱

String  i="abc";
object obj=(object)i;//装箱
object obj2="abc";
string i2=(string)obj2;//拆箱
动态(Dynamic)类型

可存储任何类型的值在动态数据类型变量中。这些变量的类型约束是在运行时发生的,被编译后本质是一个Object类型。 而var关键字在编译时静态的定义数据类型,而不是在运行时,其本质上是个语法糖,一旦被编译,编译器就会自动匹配var变量的实际类型。

dynamic d = 20;
double result = 5 / 3;
Console.WriteLine(result);//1
var result2 = (double)5 / 3;
Console.WriteLine(result2);//1.66666666666667
字符串(String)类型
  • 字符串前加 @(称作逐字字符串)将转义字符(\)当作普通字符对待。@ 字符串中可以任意换行,换行符及缩进空格都计算在字符串长度之内(类似js中的``)。
  • 字符串前加 $ (称作内插字符串)比起复合格式设置字符串更清晰易读。
  • string只是String类型的别名。
String str = "runoob.com";
string str = @"C:\Windows";//string str = "C:\\Windows";
string str = @"<script type=""text/javascript"">
</script>";

string name = "Mark";
var date = DateTime.Now;
// 复合格式设置字符串:
Console.WriteLine("Hello, {0}! Today is {1}, it's {2:HH:mm} now.", name, date.DayOfWeek, date);
// 内插字符串:
Console.WriteLine($"Hello, {name}! Today is {date.DayOfWeek}, it's {date:HH:mm} now.");
  • 空字符串
string s = String.Empty;  
获取实例的类型 .GetType()

不能对null使用,null没有类型

Console.WriteLine(10.GetType());//System.Int32

类型转换(变量本身的数据类型不变)

  • 隐式类型转换,仅能子类转化为基类
  • 显式类型转换,需要强制转换运算符
    • (int)a中,a仅能为数字
    • Convert.ToXXX(a)可以实现基本类型间的各种转换
    • 字符串类型转换为对应的基本类型用类型名.Parse()方法,基本类型转化成字符串用.ToString()
double a = 123.11;
int b = 555;
b = (int)a;
var c = Convert.ToInt32(a);
var d = a.ToString();
var e = Int32.Parse(d);

可空类型 Nullable

对于所有不可为 null 的值类型 T,都有对应的可空类型 T?Nullable<T>,可以包含附加值 null

int? i = 3;
Nullable<int> i = new Nullable<int>(3);
判断是否为空
  • 通过 ==!= 可用于判断是否为空
  • 只读属性.HasValue可用于判断一个可空值是否有值
  • 只读属性.Value可用于获取一个可空值的值
int? x = 3;
int y;
if (x.HasValue)   y = x.Value;
if (x != null)   y = x.Value;
Null 合并运算符 ??

如果第一个操作数的值为 null,则运算符返回第二个操作数的值,否则返回第一个操作数的值。
此时被赋值的变量类型会变得允许为空,可用于将可空类型转变为基础类型(或使用.GetValueOrDefault()方法)。

double? num = 3.14157;
double num1;
num1 = num ?? 5.34;      // num 如果为空值则返回 5.34
Null 条件运算符

借助 ?.?[](null 条件)运算符,可轻松编写包含 null 值的逻辑,无需额外的 if 检查。

string s = null;
Console.WriteLine(s.Length);
char? c = s?[0];
Console.WriteLine(c.HasValue);

string s = null;
bool? hasMore = s?.ToCharArray()?.GetEnumerator()?.MoveNext();
Console.WriteLine(hasMore.HasValue);

string s = null;
bool hasMore = s?.ToCharArray()?.GetEnumerator()?.MoveNext() ?? false;
Console.WriteLine(hasMore);

获取变量/类/类成员的名称 nameof()

Console.WriteLine(nameof(System.String));//String
int j = 5;
Console.WriteLine(nameof(j));//j
List<string> names = new List<string>();
Console.WriteLine(nameof(names));//names

运算符

运算符优先级同js

  • 算术运算符 + - * / % ++ --
  • 关系运算符
    • > < >= <= 可用于整数与浮点数之间
    • == != 只能比较完全相同类型的变量
  • 逻辑运算符 && || !
    不同于js,只能直接比较布尔值,并返回布尔值
  • 位运算符 << >> & ^ | ~
  • 赋值运算符 = += -= *= /= %= <<= >>= &= ^= |=
  • 其他运算符
    • sizeof() 返回目标变量/类型的大小。
    • typeof() 返回 class 的类型。(对实例应使用.GetType()方法)
    • & 返回变量的地址。
    • * 变量的指针。
    • ?: 条件表达式。
    • is 判断对象是否为某一类型。(null 不属于任何类型)
    • as 强制转换(不能应用在值类型数据)
Animal animal = new Animal() as Person;

语句

声明语句

变量

可以在声明时被初始化(赋予一个初始值)

int d = 3, f = 5;
d = Convert.ToInt32(Console.ReadLine());//其中Console.ReadLine()接收的总为字符串
常量

常量可以被当作常规的变量,只是它们的值在定义后不能被修改。
使用const定义常量

public const int c2 = c1 + 5;

选择语句

  • if ... else if ... else
  • switch

迭代语句

  • while

  • do...while

  • for 与js相同,for的(){}中均非局部作用域

  • foreach

foreach(int i in new int[]{ 1, 2, 3 })
{
  Console.WriteLine(i+5);
}
Console.ReadLine();//6 7 8

跳转语句

  • break
  • continue
  • goto
static void GoToStatement(string[] args)
{
    int i = 0;
    goto check;
    loop:
    Console.WriteLine(args[i++]);
    check:
    if (i < args.Length) 
        goto loop;
}
  • throw
  • return
  • yield
static System.Collections.Generic.IEnumerable<int> Range(int start, int end) 
{
    for (int i = start; i < end; i++) 
    {
        yield return i;
    }
    yield break;
}
static void YieldStatement(string[] args)
{
    foreach (int i in Range(-10,10)) 
    {
        Console.WriteLine(i);
    }
}

异常处理

  • try {...} catch(e){...} finally{}

其他语句

checked 和 unchecked 语句

用于控制整型类型算术运算和转换的溢出检查上下文。

static void CheckedUnchecked(string[] args) 
{
    int x = int.MaxValue;
    unchecked 
    {
        Console.WriteLine(x + 1);  // Overflow
    }
    checked 
    {
        Console.WriteLine(x + 1);  // Exception
    }     
}
lock 语句

用于获取给定对象的相互排斥锁定,执行语句,然后解除锁定。

class Account
{
    decimal balance;
    private readonly object sync = new object();
    public void Withdraw(decimal amount) 
    {
        lock (sync) 
        {
            if (amount > balance) 
            {
                throw new Exception(
                    "Insufficient funds");
            }
            balance -= amount;
        }
    }
}
using语句

using 语句用于获取资源,执行语句,然后释放资源。
using 语句中使用的对象必须实现 IDisposable 接口(Windows内核对象、文件操作、数据库连接、socket、Win32API、网络等)。执行结束后会释放资源。
using语句支持初始化多个变量,但前提是这些变量的类型必须相同

static void UsingStatement(string[] args) 
{
  using (Font font3=new Font("Arial",10.0f), font4=new Font("Arial",10.0f))
    {
      // Use font3 and font4.
    }
}
  • using 实质
    在程序编译阶段,编译器会自动将using语句生成为try-finally语句,并在finally块中调用对象的Dispose方法,来清理资源。所以,using语句等效于try-finally语句,例如:
using (Font f2 = new Font("Arial", 10, FontStyle.Bold))
{
  font2.F();
}

被编译器翻译为:

   Font f2 = new Font("Arial", 10, FontStyle.Bold);
  try
  {
      font2.F();
  }
  finally
  {
      if (f2 != null) ((IDisposable)f2).Dispose();
  }
Expression-Bodied立即返回表达式 和 lambda表达式

Expression-Bodied用于单个语句作为方法主体的方法定义:

public Point Move(int dx, int dy) => new Point(x + dx, y + dy);
public void Print() => Console.WriteLine(First + " " + Last);
// Works with operators, properties, and indexers too.
public static Complex operator +(Complex a, Complex b) => a.Add(b);
public string Name => First + " " + Last;
public Customer this[long id] => store.LookupCustomer(id);
public string FirstName
{
  get => firstName;
  set => firstName = value;
}

lambda表达式用于转换委托

Func<int, int> square = x => x * x;
...
Action<string> greet = name => 
{ 
    string greeting = $"Hello {name}!";
    Console.WriteLine(greeting);
};
greet("World");
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,839评论 6 482
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,543评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 153,116评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,371评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,384评论 5 374
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,111评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,416评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,053评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,558评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,007评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,117评论 1 334
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,756评论 4 324
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,324评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,315评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,539评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,578评论 2 355
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,877评论 2 345