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.