接口聲明可以有任何的訪問修飾符public柑爸,internal表鳍,protected和private譬圣。
接口的成員是隱式public的,不允許有任何訪問修飾符
只有類和結構才能實現(xiàn)接口
- 在基類列表中包括接口名稱
- 為每一個接口的成員提供實現(xiàn)
關于實現(xiàn)接口:
- 如果類實現(xiàn)了接口绳姨,他必須實現(xiàn)接口的所有成員
-
如果類從基類繼承并實現(xiàn)接口,基類列表中的基類名稱必須放在任何接口之前
簡單接口實例
接口是引用類型
接口不僅僅是類和結構要實現(xiàn)的成員列表,它是一個引用類型
從類對象引用獲取接口引用的實例
這段代碼輸出結果為:
Calling through: object.
Calling through: interface.
接口和as運算符
當嘗試強制轉換類對象引用為類未實現(xiàn)的接口的引用,強制轉換操作會拋出一個異常廓旬。可以通過使用as運算符來避免
- 如果類實現(xiàn)了接口励背,表達式返回指向接口的引用
- 如果沒有叶眉,表達式返回null而不是拋出異常
實現(xiàn)多個接口
- 類和結構可以實現(xiàn)任意數(shù)量的接口
-
所有實現(xiàn)的接口必須列在基類列表中并以逗號分隔
實現(xiàn)具有重復成員的接口
如果一個類實現(xiàn)了多個接口,那么其中一些接口有相同簽名和返回類型的成員。類可以實現(xiàn)單個成員來滿足包含重復成員的接口
多個接口的引用
派生成員作為實現(xiàn)
實現(xiàn)接口的類可以從他的基類繼承實現(xiàn)的代碼
顯示接口成員實現(xiàn)
使用限定接口名稱來聲明,有接口名稱和成員名稱以及他們中間的點分隔符號構成
訪問顯示接口成員實現(xiàn)
顯示接口成員實現(xiàn)只可以通過指向接口的引用來訪問嗽上,也就是說其他的類成員都不可以直接訪問它們兽愤。
接口可以繼承接口
接口本身可以從一個或多個接口繼承
結果接口包含它聲明的所有接口和所有基類的成員逐沙。
轉換
- 轉換時接受一個類型的值并使用他作為另一個類型的等價值的過程
- 轉換后的值應和源值一樣的,但他是目標類型
用戶自定義轉換
is運算符
is運算符語法如下,expr是源表達式
如果expr成功轉換為目標類型,運算符返回true
is運算符只可用于引用轉換以及裝箱和拆箱轉換抱环,不能用于用戶自定義轉換
as運算符
as運算符語法如下镇草,expr是源表達式
targettype是目標類型,他必須是引用類型
轉換失敗返回null
泛型
c#提供了五種泛型:類条辟,結構羽嫡,接口,委托和方法魂爪。前四個是類型滓侍,方法是成員
這是為多段代碼在不同的數(shù)據類型執(zhí)行相同指令的情況專門設計的
聲明泛型類
創(chuàng)建構造類型
要替代類型參數(shù)的真實類型叫做類型實參
- 泛型類聲明有類型參數(shù)
- 在創(chuàng)建構造類型時提供的真實類型是類型實參夕冲。
創(chuàng)建變量和實例
class MyStack<T>
{
int StackPointer = 0;
T[] StackArray;
public void Push(T x)
{
if (!IsStackFull)
{
StackArray[StackPointer++] = x;
}
}
public T Pop()
{
return (!IsStackEmpty)
? StackArray[--StackPointer]
: StackArray[0];
}
const int MaxStack = 10;
bool IsStackFull
{
get
{
return StackPointer >= MaxStack;
}
}
bool IsStackEmpty
{
get
{
return StackPointer <= 0;
}
}
public MyStack()
{
StackArray = new T[MaxStack];
}
public void Print()
{
for (int i = StackPointer-1; i >=0; i--)
{
Console.WriteLine("value:{0}",StackArray[i]);
}
}
}
class Program
{
static void Main(string[] args)
{
var stackInt = new MyStack<int>();
var stackString = new MyStack<string>();
stackInt.Push(3);
stackInt.Push(5);
stackInt.Push(7);
stackInt.Print();
stackString.Push("Generics are great!");
stackString.Push("Hi there!");
stackString.Print();
Console.ReadKey();
}
}
返回結果為:
value:7
value:5
value:3
value:Hi there!
value:Generics are great!
非泛型 | 泛型 | |
---|---|---|
源代碼大小 | 更大:我們需要為每一種類型進行一個新的實現(xiàn) | 更忻忠觥:不管構造類型的數(shù)量有多少蚁阳,我們只需要一個實現(xiàn) |
可執(zhí)行大小 | 無論每一個版本的棧是否會被使用螺捐。都會在編譯的版本中出現(xiàn) | 可執(zhí)行文件中只會出現(xiàn)有構造類型的類型 |
寫的難易度 | 易于書寫 | 比較難寫 |
維護的難易度 | 更容易出問題,因為所有修改需要應用到每一個可用的類型上 | 易于維護澜沟,因為只需要修改一個地方 |
類型參數(shù)的約束
要讓泛型變得更有用,我們需要提供額外的信息讓編譯器知道參數(shù)可以接受哪些類型濒析。這些額外的信息叫做約束号杏。只有符合約束的實參才能用于類型參數(shù)。
Where子句
每一個有約束的類型參數(shù)有自己的where子句
where子句可以以任何次序列出,然而蜈块,where子句中的約束必須有特定的順序:
- 最多只能有一個主約束爽哎,有則放在第一位
- 可以有人一多的interfacename約束课锌。
-
如果存在構造函數(shù)約束渺贤,則必須放在最后志鞍。
泛型接口
輸出結果為:
5
Hi There.
使用泛型接口的示例
實現(xiàn)同一泛型接口的兩個不同接口
泛型接口的名字不會和非泛型接口的名字沖突
泛型委托
泛型方法
調用泛型方法
泛型方法示例
擴展方法和泛型類
和非泛型擴展方法一樣委粉,泛型類的擴展方法:
- 必須聲明為static贾节;
- 必須是靜態(tài)類的成員栗涂;
- 第一個參數(shù)類型中必須有關鍵字this送爸,后面是擴展的泛型類的名字
介紹LINQ
- LINQ代表語言集成查詢
- LINQ是.NET框架的擴展袭厂,它允許我們以數(shù)據庫查詢的方式查詢數(shù)據集合
- 允許我們從數(shù)據庫纹磺,程序對象集合以及XML文檔中查詢數(shù)據
class Program
{
static void Main(string[] args)
{
int[] numbers = { 2, 15, 5, 25 };
IEnumerable<int> lowNums = //定義并儲存查詢
from n in numbers
where n < 10
select n;
foreach (var item in lowNums)
{
Console.WriteLine(item);
}
Console.ReadKey();
}
}
輸出結果如下:
2
5
匿名類型
匿名類型的對象初始化器還有其它兩種允許的形式:簡單標識符和成員訪問表達式。這兩種形式叫做投影初始化器乡摹。
查詢語法和方法語法
- 查詢語法是聲明形式的,看上去和SQL語句很相似板熊。查詢語法適應查詢表達式形式書寫
-
方法語法是命令形式的干签,他使用標準的方法調用。方法是一組叫做標準查詢運算符的方法。
其中方法語法采用的是lambda表達式
LINQ中from子句和foreach語句主要的不同點
- foreach語句在遇到代碼是就執(zhí)行器主體,而from子句什么也不執(zhí)行睁宰。它創(chuàng)建一個用于保存查詢變量的可枚舉對象柒傻,查詢本身會在之后的代碼中被執(zhí)行或不被執(zhí)行
- foreach語句明確指定集合中的項需要按照次序,從第一個到最后一個预侯。而fromn子句只是聲明性的規(guī)定了必須考慮集合中的每一個項萎馅,不規(guī)定其順序飒货。
join子句
let子句
let子句接受一個表達式的運算并且把它賦值給一個需要在其他運算中使用的標識符
where子句
orderby
查詢中的匿名類型
group子句
異步
namespace yibu
{
delegate long MyDel(int first, int second); //聲明委托類型
class Program
{
public static long Sum(int x,int y) //聲明異步方法
{
Console.WriteLine(" inside sum");
Thread.Sleep(3000); //掛起三秒
return x + y;
}
static void Main(string[] args)
{
MyDel del = new MyDel(Sum); //創(chuàng)建委托并引用
Console.WriteLine("異步調用之前");
IAsyncResult iar = del.BeginInvoke(3, 6, null, null); //開始異步調用
Console.WriteLine("異步調用之后");
Console.WriteLine("Doing stuff");
long result = del.EndInvoke(iar); //等待結束并獲取結果
Console.WriteLine(result);
Console.ReadKey();
}
}
}
輸出結果為:
異步調用之前
異步調用之后
Doing stuff
inside sum
9