c# 個人筆記
阿新 • • 發佈:2020-12-08
基礎
靜態--static
抽象--abstract
值型別
型別 | 描述 | 範圍 | 預設值 |
---|---|---|---|
bool | 布林值 | True 或 False | False |
byte | 8 位無符號整數 | 0 到 255 | 0 |
char | 16 位 Unicode 字元 | U +0000 到 U +ffff | '\0' |
decimal | 128 位精確的十進位制值,28-29 有效位數 | (-7.9 x 1028 到 7.9 x 1028) / 100 到 28 | 0.0M |
double | 64 位雙精度浮點型 | (+/-)5.0 x 10-324 到 (+/-)1.7 x 10308 | 0.0D |
float | 32 位單精度浮點型 | -3.4 x 1038 到 + 3.4 x 1038 | 0.0F |
int | 32 位有符號整數型別 | -2,147,483,648 到 2,147,483,647 | 0 |
long | 64 位有符號整數型別 | -9,223,372,036,854,775,808 到 9,223,372,036,854,775,807 | 0L |
sbyte | 8 位有符號整數型別 | -128 到 127 | 0 |
short | 16 位有符號整數型別 | -32,768 到 32,767 | 0 |
uint | 32 位無符號整數型別 | 0 到 4,294,967,295 | 0 |
ulong | 64 位無符號整數型別 | 0 到 18,446,744,073,709,551,615 | 0 |
ushort | 16 位無符號整數型別 | 0 到 65,535 | 0 |
值傳遞
引用傳遞--ref
介面
什麼是介面?
- 介面就是一種規範,協議(*),約定好遵循某種規範就可以寫通用的程式碼。
- 定義了一組具有各種功能的方法。(只是一種能力,沒有具體實現,像抽象方法一樣,“光說不做”)。
介面存在的意義
- 多型,程式可拓展性,讓程式變得更靈活,節省成本,提高效率。
- 介面解決了類的多繼承的問題。
- 介面解決了類的繼承以後體積龐大的問題。
- 介面之間可以實現多繼承。
總結
- 子類繼承抽象類,實現介面(介面中定義的方法)。
- 介面中的成員必須不能有實現,介面不能例項化。
- 介面中的成員不能有訪問修飾符(public、private等),預設是public。
- 介面中可以有屬性、方法、索引器等(其實這些都是方法),但不能有欄位。
- 就扣中的所有成員必須被子類中全部實現,除非子類是抽象類,把就扣中的成員標記為抽象的。
- 當一個類同時繼承父類,並且實現多個介面的時候,必須將繼承類寫在第一個,然後再用逗號隔開再寫介面
- 顯示實現介面沒有訪問修飾符,預設是私有的。
- 顯示實現介面時,在方法名稱前加了介面名,如:介面名.方法
異常處理
什麼是異常?
程式執行時發生的錯誤。(錯誤並不一定是程式設計師的原因,例如:伺服器關閉或者資料庫關閉,導致程式無法獲取資料等;操作的對應檔案沒了,或者檔案許可權被修改導致許可權不足等;程式內計算數值時被除數為0;使用物件時物件重新賦值為null;)
當程式發生異常後不進行處理會導致整個程式直接崩潰。
處理異常的一般程式碼模式
using System;
namespace ConsoleApp1
{
class Program
{
static void Main(string[] args)
{
try
{
//可能發生異常的程式碼,當遇到異常時後續程式碼不執行
}
catch
{
//處理異常的程式碼,記錄日誌(log4net),繼續向上丟擲等操作
//只有發生了異常才會執行此處程式
}
finally
{
//此處程式碼無論是否發生異常都會執行
//程式碼清理,資源釋放等
}
}
}
}
案例
using System;
namespace ConsoleApp1
{
class Program
{
static void Main(string[] args)
{
Person p = new Person();
p = null;
p.Name = "張三";
Console.WriteLine(p.Name);
Console.ReadKey();
}
}
public class Person
{
public string Name { get; set; }
public int Age { get; set; }
}
}
執行結果
catch的多種寫法
寫法一
using System;
namespace ConsoleApp1
{
class Program
{
static void Main(string[] args)
{
try
{
int n = 20, m = 0;
int sum = n / m;
Console.WriteLine(sum);
}
//可以獲取try內的所有異常,但是無法獲取具體異常
catch
{
Console.WriteLine("發生了異常!");
}
}
}
}
寫法二
using System;
namespace ConsoleApp1
{
class Program
{
static void Main(string[] args)
{
try
{
int n = 20, m = 0;
int sum = n / m;
Console.WriteLine(sum);
}
//可以獲取所有異常,並且可以獲取指定的異常資訊
catch(Exception e)
{
Console.WriteLine("發生異常");
Console.WriteLine(e.Message); //異常資訊
Console.WriteLine(e.Source); //發生異常的具體物件
Console.WriteLine(e.StackTrace); //發生異常的堆疊
}
}
}
}
方法三
using System;
namespace ConsoleApp1
{
class Program
{
static void Main(string[] args)
{
try
{
int n = 20, m = 0;
int sum = n / m;
Console.WriteLine(sum);
}
//對不同的異常採用不同的方式處理(使用多個catch捕獲異常)
catch(NullReferenceException e)
{
Console.WriteLine("空指標異常:{0}",e.Message);
}
catch(DivideByZeroException e)
{
Console.WriteLine("除數為0,詳細資訊:{0}",e.StackTrace);
}
catch(ArgumentException e)
{
Console.WriteLine("引數異常,詳細資訊:{0}",e.StackTrace);
}
catch(Exception e)
{
//捕獲所有異常,放在其他捕獲異常後面
Console.WriteLine(e.StackTrace);
}
Console.ReadKey();
}
}
}
finally
當
catch
有無法捕獲到的異常時,程式崩潰,但在程式崩潰前會執行finally
中的程式碼,而finally
塊後的程式碼則由於程式崩潰後無法執行。如果在catch塊中又引發了異常,則
finally
塊中的內碼表會在繼續引發異常之前執行,但是在finally
後面的程式碼則不會執行。當catch塊中有
return
語句時,finally
中的程式碼會在return
之前執行,但是finally
塊之後的程式碼不會執行。
throw
throw new Exception
using System;
namespace ConsoleApp1
{
class Program
{
static void Main(string[] args)
{
while (true)
{
try
{
Console.WriteLine("請輸入一個名字:");
string name = Console.ReadLine();
if (name == "張三")
{
//手動寫異常資訊(不推薦使用)
throw new Exception("名字錯誤!");
}
else
{
Console.WriteLine("名字正確:{0}", name);
}
}
catch (Exception e)
{
Console.WriteLine("發生異常!");
Console.WriteLine(e.Message);
Console.WriteLine(e.StackTrace);
}
}
}
}
}
throw
using System;
namespace ConsoleApp1
{
class Program
{
static void Main(string[] args)
{
M1();
}
static void M1()
{
try
{
int n = 20, m = 0;
int sum = n / m;
Console.WriteLine("結果:{0}",sum);
}
catch (Exception)
{
Console.WriteLine("捕獲了異常並進行了處理!");
throw;
}
}
}
}
throw表示如果還有異常則向上丟擲,如果不寫的話在其他地方呼叫M1這個方法
的時候又引發了其他異常則無法捕獲throw單獨寫時只能在catch塊中寫
字串操作
判斷是否為同一個物件?
判斷物件的三種方法(==,等於,ReferenceEquals)
using System;
namespace ConsoleApp1
{
class Program
{
static void Main(string[] args)
{
Person p1 = new Person();
p1.Name = "張三";
p1.Age = 18;
p1.Email = "[email protected]";
Person p2 = new Person();
p2.Name = "張三";
p2.Age = 18;
p2.Email = "[email protected]";
p2 = p1;
Console.WriteLine(p1 == p2);
Console.WriteLine(p1.Equals(p2));
Console.WriteLine(object.ReferenceEquals(p1,p2));
Console.ReadKey();
}
}
public class Person
{
public string Name { get; set; }
public int Age { get; set; }
public string Email { get; set; }
}
}
上面輸出的結果都為True
using System;
namespace ConsoleApp1
{
class Program
{
static void Main(string[] args)
{
string str1 = new string(new char[] { 'a', 'b', 'c' });
string str2 = new string(new char[] { 'a', 'b', 'c' });
Console.WriteLine(str1);//abc
Console.WriteLine(str2);//abc
Console.WriteLine(str1==str2);//true
Console.WriteLine(str1.Equals(str2));//true
Console.WriteLine(object.ReferenceEquals(str1,str2));//false
Console.ReadKey();
}
}
}
上面這段程式碼的輸出結果和之前的不一樣了,有兩種輸出結果。是什麼原因導致了兩種不同的結果呢?
Equals
public static bool Equals(string a, string b)
{
if (a == b)
{
return true;
}
if ((a == null) || (b == null))
{
return false;
}
if (a.Length != b.Length)
{
return false;
}
return EqualsHelper(a, b);
}
==
public static bool operator ==(string a, string b) =>
Equals(a, b);
ReferenceEquals
public static bool ReferenceEquals(object objA, object objB) =>
((bool) (objA == objB));
通過反編譯之後發現,Equals與==都是對比字串,當字串的內容一樣,長度一樣,那麼對比結果就是True。然而ReferenceEquals則是對比object型別的資料,是對比的物件,需要生成的物件一致才行,在上面演示程式碼處,使用了new來生成兩個新的物件,那麼這兩個就不是同一個物件了,所以返回false。
在地址堆疊中,只是宣告兩個變數(如string str = "hello";string str1 = "hello"