為什麼要用泛型?那麼先來看下面兩個功能相似的非泛型類
這個類都是int
class myintstack
}
這個類都是float
class myfloatstack
}
第乙個類實現了int型的功能,第二個類通過剪下、改類名、將int改為float實現float型功能,通過這種方式的變換實現float型功能當然可行,但有以下缺點:
a、需檢查類宣告哪些需更改,哪些需保留
b、每次新增新型別(long、double...)等時都要重寫**
c、有很多相同**副本,占用空間
d、除錯和維護複雜且易出錯
泛型提供了這些問題的更好的解決方式
泛型可讓多個型別共享一組**,泛型允許我們宣告型別引數化的**,可以用不同的型別進行例項化。也就是說,我們可以用「型別佔位符」來寫**,然後在建立類的例項時指明真實的型別
c#提供了5種泛型:類、結構、介面、委託和方法
示例:
class stack
}
注意:
a、在類名之後放置一組尖括號
b、在尖括號中用逗號分隔的佔位符字串來表示希望提供的型別,佔位字串叫做型別引數
c、在泛型類宣告的主體中使用型別引數來表示應該替換的型別
class someclass
作用:告訴編譯器能使用哪些真是型別來替代佔位符(型別引數),編譯器獲取這些真實型別來建立構造型別(即建立真實類物件的模板)。要替代型別引數的真是型別叫做型別實參
someclass
建立了類的模板後,我們還要將他例項化才可使用,例項化也就意味著賦給變數,所以要建立變數
someclassmysc1 = new someclass();
var mysc2 = new someclass();
注意例項化的<>()
using system;
class mystack
public t pop()
const int maxstack = 10;
bool isstackfull
}bool isstackempty
}public mystack()
public void print()
", stackarray[i]);
}}class program
}
知識回顧:
條件運算子、屬性
where約束t必須繼承自某一介面,方便我們呼叫t裡面的方法。
// irole的作用是約束傳入的兩個引數型別必須要實現irole這個介面;
public bool comparelevel(t t1, k t2) where t : irole where k : irole
//那麼怎麼使用泛型呢?
public void test()
public inte***ce irole
}public class myplayer : irole
}public class mynpc : irole
}public class mymonster : irole
}
擴充套件方法回顧
和非泛型類一樣,泛型類的擴充套件方法:
a、必須宣告為static
靜態類不必生成新的例項,main方法可直接呼叫另乙個類(靜態類為此類擴充套件類,間接呼叫擴充套件類)
靜態類內為靜態成員
b、第乙個引數型別中必須有關鍵字this,後面是擴充套件的泛型類的名字
using system;
class a
public void getvalues()
,,",vals[0], vals[1], vals[2]);
}}static class b
}class program
}
與泛型類相似,泛型結構可以有型別引數和約束。泛型結構的規則和條件與泛型類是一致的
using system;
struct pwhere t : struct
set
}}class program
}
委託知識回顧
using system;
public delegate string func(t1 p1, t2 p2);
class ******
}class program
", mydel(15, 13));
console.writeline("total:", new func(******.printstring)(15, 13));
//傳入的方法數值應該傳入的方法之後!
}}
本例中委託形參負責將資料傳入委託中的方法。委託返回型別為string,是因為委託中的方法返回型別為string,當然委託型別為object也是可以的
泛型介面允許我們編寫引數和介面成員返回型別都是泛型型別引數的介面。泛型介面的宣告和非泛型介面的宣告差不多
using system;
inte***ce iif
class ******: iif
}class program
}
這樣可繼承多個不同實際型別引數,若是只寫繼承乙個介面而希望實現兩個介面,那是系統所不允許的,因為那可能出現兩個相同型別引數,造成衝突
using system;
inte***ce iif
class ******: iif,iif
public string returnit(string invalueb)
}class program
}
class ****** : iif, iif//報錯,因為s可能為int型,類會產生兩個重複的介面,這是不允許的
public s returnit(s invalue)
}
泛型介面名字不會和非泛型衝突(若都是泛型或非泛型,出現相同的介面名,則會衝突),我們還可宣告乙個跟泛型名字一樣的非泛型介面,如下**所示
inte***ce iif
inte***ce iif
認真CS丨堆疊
堆疊 stack 代表了乙個後進先出的物件集合。當向堆疊列表中新增一項,稱為推入元素。當從堆疊列表中移除一項時,稱為彈出元素。堆疊使用方法如下 stackobjs new stack objs.clear 移除 堆疊objs 所有元素 bool iscon objs.contains gameobj...
認真CS丨列舉器
實現了ienumerator介面的類稱為列舉器 using system.runtime.interopservices namespace system.collections 摘要 將列舉數推進到集合的下乙個元素。返回結果 如果列舉數已成功地推進到下乙個元素,則為 true 如果列舉數傳遞到集合...
認真CS丨yield迭代
首先我們來說下迭代的目的 迭代是將自定義類變為自定義類陣列,並遍歷它 在c 1.0和c 2.0這兩個版本中,c 2比c 1多了乙個更簡潔的迭代方法 1 定義單個類 2 定義這個類的陣列的列舉器方法 3 定義getenumerator方法 4 對該類陣列賦值,並例項化3getenumerator方法,...