Typy a členové
Jazyk C# podporuje koncepty zapouzdření, dědičnosti a polymorfismus jako objektově orientovaného jazyka. Třída může dědit přímo z jedné nadřazené třídy a může implementovat libovolný počet rozhraní. Metody, které přepisují virtuální metody v nadřazené třídě, vyžadují override klíčové slovo jako způsob, jak se vyhnout náhodnému předefinování. V jazyce C# je struktura podobně jako odlehčená třída; Jedná se o typ přidělený zásobníkem, který může implementovat rozhraní, ale nepodporuje dědění. Jazyk C# poskytuje record class record struct typy, které jsou typy, jejichž účelem je primárně ukládání hodnot dat.
Třídy a objekty
Třídy jsou základem typů jazyka C#. Třída je datová struktura, která kombinuje stav (pole) a akce (metody a další členy funkce) v jedné jednotce. Třída poskytuje definici pro instance třídy, označované také jako objekty. Třídy podporují Dědičnost a polymorfismus, mechanismy, kterými mohou odvozené třídy roztáhnout a specializovat základní třídy.
Nové třídy jsou vytvářeny pomocí deklarací třídy. Deklarace třídy začíná hlavičkou. Záhlaví určuje:
- Atributy a modifikátory třídy
- Název třídy
- Základní třída (při dědění ze základní třídy)
- Rozhraní implementovaná třídou.
Pod hlavičkou následuje tělo třídy, které se skládá ze seznamu deklarací členů napsaných mezi oddělovači { a } .
Následující kód ukazuje deklaraci jednoduché třídy s názvem Point :
public class Point
{
public int X { get; }
public int Y { get; }
public Point(int x, int y) => (X, Y) = (x, y);
}
Instance tříd jsou vytvořeny pomocí new operátoru, který přiděluje paměť pro novou instanci, vyvolá konstruktor pro inicializaci instance a vrátí odkaz na instanci. Následující příkazy vytvoří dva Point objekty a ukládají odkazy na tyto objekty ve dvou proměnných:
var p1 = new Point(0, 0);
var p2 = new Point(10, 20);
Paměť obsazená objektem je automaticky uvolněna v případě, že objekt již není dostupný. Není nutné nebo je možné explicitně uvolnit objekty v jazyce C#.
Parametry typu
Obecné třídy definují parametry typu. Parametry typu jsou seznam názvů parametrů typu uzavřených do lomených závorek. Parametry typu následují za názvem třídy. Parametry typu lze potom použít v těle deklarací třídy k definování členů třídy. V následujícím příkladu parametry typu Pair jsou TFirst a TSecond :
public class Pair<TFirst, TSecond>
{
public TFirst First { get; }
public TSecond Second { get; }
public Pair(TFirst first, TSecond second) =>
(First, Second) = (first, second);
}
Typ třídy, která je deklarována pro přijetí parametrů typu, se nazývá typ obecné třídy. Typy struktury, rozhraní a delegátů můžou být také obecné. Při použití obecné třídy je nutné zadat argumenty typu pro každý z parametrů typu:
var pair = new Pair<int, string>(1, "two");
int i = pair.First; //TFirst int
string s = pair.Second; //TSecond string
Obecný typ s poskytnutými argumenty typu, jako Pair<int,string> je například výše, se označuje jako konstruovaný typ.
Základní třídy
Deklarace třídy může určovat základní třídu. Použijte název třídy a parametry typu s dvojtečkou a názvem základní třídy. Vynechání specifikace základní třídy je stejné jako odvození z typu object . V následujícím příkladu je základní třída třídy Point3D Point . V prvním příkladu je základní třída Point object :
public class Point3D : Point
{
public int Z { get; set; }
public Point3D(int x, int y, int z) : base(x, y)
{
Z = z;
}
}
Třída dědí členy své základní třídy. Dědičnost znamená, že třída implicitně obsahuje skoro všechny členy své základní třídy. Třída nedědí instance a statické konstruktory a finalizační metodu. Odvozená třída může přidat nové členy do těch členů, které dědí, ale nemůže odebrat definici zděděného člena. V předchozím příkladu Point3D dědí X Y Členové a z Point a každá Point3D instance obsahuje tři vlastnosti, X , Y a Z .
Implicitní převod existuje z typu třídy na libovolný z jeho základních typů třídy. Proměnná typu třídy může odkazovat na instanci této třídy nebo instance jakékoli odvozené třídy. Například s ohledem na předchozí deklarace třídy může proměnná typu Point odkazovat buď na, Point nebo Point3D :
Point a = new(10, 20);
Point b = new Point3D(10, 20, 30);
Struktury
Třídy definují typy, které podporují dědičnost a polymorfismuy. Umožňují vytvářet sofistikovaná chování založená na hierarchiích odvozených tříd. Naopak typy struktury jsou jednodušší typy, jejichž primárním účelem je ukládání hodnot dat. Struktury nemůžou deklarovat základní typ; implicitně se odvozují z System.ValueType . Z typu nelze odvodit jiné struct typy struct . Jsou implicitně zapečetěné.
public struct Point
{
public double X { get; }
public double Y { get; }
public Point(double x, double y) => (X, Y) = (x, y);
}
Rozhraní
* Rozhraní _ definuje kontrakt, který lze implementovat pomocí tříd a struktur. Definujete _interface * pro deklaraci schopností, které jsou sdíleny mezi různými typy. System.Collections.Generic.IEnumerable<T>Rozhraní například definuje konzistentní způsob, jak procházet všechny položky v kolekci, jako je pole. Rozhraní může obsahovat metody, vlastnosti, události a indexery. Rozhraní obvykle neposkytuje implementace členů, které definuje – určuje pouze členy, které musí být poskytnuty třídami nebo strukturami, které implementují rozhraní.
Rozhraní mohou využívat vícenásobnou dědičnost. V následujícím příkladu rozhraní IComboBox dědí z ITextBox a IListBox .
interface IControl
{
void Paint();
}
interface ITextBox : IControl
{
void SetText(string text);
}
interface IListBox : IControl
{
void SetItems(string[] items);
}
interface IComboBox : ITextBox, IListBox { }
Třídy a struktury mohou implementovat více rozhraní. V následujícím příkladu třída EditBox implementuje i IControl IDataBound .
interface IDataBound
{
void Bind(Binder b);
}
public class EditBox : IControl, IDataBound
{
public void Paint() { }
public void Bind(Binder b) { }
}
Pokud třída nebo struktura implementuje konkrétní rozhraní, instance této třídy nebo struktury lze implicitně převést na tento typ rozhraní. Například
EditBox editBox = new();
IControl control = editBox;
IDataBound dataBound = editBox;
Výčty
Typ výčtu definuje sadu konstantních hodnot. Následující enum deklaruje konstanty, které definují jinou kořenovou zeleninu:
public enum SomeRootVegetable
{
HorseRadish,
Radish,
Turnip
}
Můžete také definovat enum , který má být použit v kombinaci jako příznaky. Následující deklarace deklaruje sadu příznaků pro čtyři období. Může se použít libovolná kombinace období, včetně All hodnoty, která zahrnuje všechny sezóny:
[Flags]
public enum Seasons
{
None = 0,
Summer = 1,
Autumn = 2,
Winter = 4,
Spring = 8,
All = Summer | Autumn | Winter | Spring
}
Následující příklad ukazuje deklarace obou předchozích výčtů:
var turnip = SomeRootVegetable.Turnip;
var spring = Seasons.Spring;
var startingOnEquinox = Seasons.Spring | Seasons.Autumn;
var theYear = Seasons.All;
Typy nullable
Proměnné libovolného typu mohou být deklarovány jako nepovolující hodnotu null _ nebo s _možnou hodnotou null_. Proměnná s možnou hodnotou null může obsahovat další null hodnotu, což značí, že žádná hodnota neexistuje. Typy hodnot s možnou hodnotou null (struktury nebo výčty) jsou reprezentovány System.Nullable<T> . Typy odkazů, které nejsou null a povolující hodnotu null, jsou reprezentované podkladovým typem odkazu. Rozlišení je reprezentované metadaty, které načte kompilátor a některé knihovny. Kompilátor poskytuje upozornění, když jsou odkazy na hodnotu null překážené bez prvotní kontroly jejich hodnoty null . Kompilátor také poskytuje upozornění, pokud jsou odkazy, které nejsou null, přiřazeny hodnotě, která může být null . Následující příklad deklaruje _hodnotu null int_ a inicializuje ji na null . Potom nastaví hodnotu na 5 . Ukazuje stejný koncept jako řetězec _ * s možnou hodnotou null *. Další informace naleznete v tématu typy hodnot s možnou hodnotou null a odkazy s možnou hodnotou null.
int? optionalInt = default;
optionalInt = 5;
string? optionalText = default;
optionalText = "Hello World.";
N-tice
Jazyk C# podporuje řazené kolekce členů, které poskytují stručnou syntaxi pro seskupení více datových prvků ve zjednodušené datové struktuře. Vytvořte instanci řazené kolekce členů deklarováním typů a názvů členů mezi ( a ) , jak je znázorněno v následujícím příkladu:
(double Sum, int Count) t2 = (4.5, 3);
Console.WriteLine($"Sum of {t2.Count} elements is {t2.Sum}.");
//Output:
//Sum of 3 elements is 4.5.
Řazené kolekce členů poskytují alternativu pro strukturu dat s více členy, bez použití stavebních bloků popsaných v dalším článku.