Beépített referenciatípusok (C# referencia)

A C# számos beépített referenciatípussal rendelkezik. Kulcsszavak vagy operátorok, amelyek szinonimák a .NET-kódtár egy típusához.

Az objektum típusa

A object típus a .NET aliasa System.Object . A C#egyesített típusrendszerében minden típus, előre definiált és felhasználó által definiált referenciatípus és értéktípus közvetlenül vagy közvetve System.Objectörököl. Bármilyen típusú értéket hozzárendelhet típusváltozókhoz object. Bármely object változó hozzárendelhető az alapértelmezett értékhez a literál nullhasználatával. Amikor egy értéktípusú változót objektummá konvertál, a rendszer azt mondja, hogy be van jelölve. Amikor egy típusváltozót object értéktípussá konvertál, a rendszer azt mondja, hogy nincs megadva. További információ: Boxing and Unboxing.

A sztring típusa

A string típus nulla vagy több Unicode-karakterből álló sorozatot jelöl. string a .NET aliasa System.String .

Bár string referenciatípus, az egyenlőség operátorai == , és != az objektumok értékeinek összehasonlítására string vannak definiálva, nem a hivatkozásokra. Az értékalapú egyenlőség intuitívabbá teszi a sztringegyenlőség tesztelését. Példa:

string a = "hello";
string b = "h";
// Append to contents of 'b'
b += "ello";
Console.WriteLine(a == b);
Console.WriteLine(object.ReferenceEquals(a, b));

Az előző példában az "Igaz" és a "Hamis" érték jelenik meg, mert a sztringek tartalma egyenértékű, de ab nem ugyanarra a sztringpéldányra hivatkozik.

A + operátor összefűzi a sztringeket:

string a = "good " + "morning";

Az előző kód létrehoz egy sztringobjektumot, amely "jó reggelt" tartalmaz.

A sztringek nem módosíthatók – a sztringobjektum tartalma nem módosítható az objektum létrehozása után. A kód írásakor például a fordító létrehoz egy új sztringobjektumot az új karaktersorozat tárolásához, és az új objektum hozzá van rendelve b. A lefoglalt memória b (amikor a "h" sztringet tartalmazta) jogosult a szemétgyűjtésre.

string b = "h";
b += "ello";

Az []operátor használható egy sztring egyes karaktereihez való olvasásra. Az érvényes indexértékek kezdőértékei 0 a sztring hosszánál kisebbek lehetnek:

string str = "test";
char x = str[2];  // x = 's';

Hasonló módon az [] operátor a sztring minden karakterét át is lehet űzni:

string str = "test";

for (int i = 0; i < str.Length; i++)
{
  Console.Write(str[i] + " ");
}
// Output: t e s t

Sztringkonstansok

A sztringkonstansok típusa string három formában írható: nyers, idézőjeles és szó szerinti.

A nyers sztringkonstansok a C# 11-től kezdve érhetők el. A nyers sztringkonstansok tetszőleges szöveget tartalmazhatnak feloldósorozatok nélkül. A nyers sztringkonstansok tartalmazhatnak szóközöket és új sorokat, beágyazott idézőjeleket és egyéb speciális karaktereket. A nyers sztringkonstansok legalább három dupla idézőjelben (""") vannak elzárva:

"""
This is a multi-line
    string literal with the second line indented.
"""

Akár három (vagy több) dupla idézőjelből álló sorozatot is felvehet. Ha a szöveghez idézőjelek beágyazott sorozata szükséges, a nyers sztring literálját szükség szerint több idézőjellel kell kezdenie és befejeznie:

"""""
This raw string literal has four """", count them: """" four!
embedded quote characters in a sequence. That's why it starts and ends
with five double quotes.

You could extend this example with as many embedded quotes as needed for your text.
"""""

A nyers sztringkonstansok általában a kezdő és záró idézőjel-sorozatokat a beágyazott szövegtől eltérő sorokban jelenítik meg. A többsoros nyers sztringkonstansok támogatják a maguk által idézett sztringeket:

var message = """
"This is a very important message."
""";
Console.WriteLine(message);
// output: "This is a very important message."

Ha a kezdő és záró idézőjelek külön sorokban vannak, a nyitó idézőjelet követő és a záró idézőjelet megelőző új vonalak nem szerepelnek a végleges tartalomban. A záró idézőjelsorozat a sztringkonstans bal szélső oszlopát diktálja. A teljes kódformátumnak megfelelő nyers sztringkonstans behúzása:

var message = """
    "This is a very important message."
    """;
Console.WriteLine(message);
// output: "This is a very important message."
// The leftmost whitespace is not part of the raw string literal

A záró idézőjelsor jobb oldalán lévő oszlopok megmaradnak. Ez a viselkedés lehetővé teszi a nyers sztringek használatát olyan adatformátumokhoz, mint a JSON, a YAML vagy az XML, ahogyan az alábbi példában látható:

var json= """
    {
        "prop": 0
    }
    """;

A fordító hibát ad ki, ha a szövegsorok bármelyike a záró idézőjelsor bal oldalára terjed ki. A nyitó és záró idézőjelsorozatok ugyanazon a sorban lehetnek, feltéve, hogy a sztringkonstans nem indul el és nem végződik idézőjellel:

var shortText = """He said "hello!" this morning.""";

A nyers sztringkonstansokat sztringinterpolációval kombinálhatja, hogy idézőjeleket és zárójeleket tartalmazzon a kimeneti sztringben.

Az idézett sztringkonstansok idézőjelek közé vannak zárva ("):

"good morning"  // a string literal

A sztringkonstansok bármilyen karakterkonstanst tartalmazhatnak. A rendszer menekülési sorozatokat tartalmaz. Az alábbi példa a fordított perjelhez, \u0066 az f betűhöz és \n az új vonalhoz használ feloldósorozatot\\.

string a = "\\\u0066\n F";
Console.WriteLine(a);
// Output:
// \f
//  F

Feljegyzés

A feloldókód \udddd (ahol dddd egy négyjegyű szám) az U+dddd Unicode karaktert jelöli. Nyolcjegyű Unicode feloldókódok is felismerhetőek: \Udddddddd.

A szó szerinti sztringkonstansok a következővel @ kezdődnek, és idézőjelek közé is vannak zárva. Példa:

@"good morning"  // a string literal

A szó szerinti sztringek előnye, hogy a feloldósorozatok feldolgozása nem történik meg, ami megkönnyíti az írást. A következő szöveg például egy teljesen minősített Windows-fájlnévnek felel meg:

@"c:\Docs\Source\a.txt"  // rather than "c:\\Docs\\Source\\a.txt"

Ha dupla idézőjelet szeretne szerepeltetni egy @idézőjeles sztringben, duplázza meg:

@"""Ahoy!"" cried the captain." // "Ahoy!" cried the captain.

UTF-8 sztringkonstansok

A .NET-ben lévő sztringek UTF-16 kódolással vannak tárolva. Az UTF-8 a webes protokollok és más fontos kódtárak szabványa. A C# 11-től kezdve hozzáadhatja az u8 utótagot egy sztringkonstanshoz az UTF-8 kódolás megadásához. Az UTF-8 literálok objektumként ReadOnlySpan<byte> vannak tárolva. Az UTF-8 sztringkonstans természetes típusa a .ReadOnlySpan<byte> Az UTF-8 sztringkonstans használata egyértelműbb deklarációt hoz létre, mint az egyenértékű System.ReadOnlySpan<T>deklaráció , ahogy az az alábbi kódban is látható:

ReadOnlySpan<byte> AuthWithTrailingSpace = new byte[] { 0x41, 0x55, 0x54, 0x48, 0x20 };
ReadOnlySpan<byte> AuthStringLiteral = "AUTH "u8;

Az UTF-8 sztringkonstans tömbként való tárolásához a literál értékét tartalmazó bájtok másolása ReadOnlySpan<T>.ToArray() szükséges a mutable tömbbe:

byte[] AuthStringLiteral = "AUTH "u8.ToArray();

Az UTF-8 sztringkonstansok nem fordítási időállandók; futásidejű állandók. Ezért nem használhatók alapértelmezett értékként egy opcionális paraméterhez. Az UTF-8 sztringkonstansok nem kombinálhatók sztringinterpolációval. Nem használhatja a $ jogkivonatot és az u8 utótagot ugyanazon a sztringkifejezésen.

A meghatalmazott típusa

A delegált típusú deklaráció hasonló a metódus-aláíráshoz. Visszatérési értékkel és bármilyen típusú paraméterrel rendelkezik:

public delegate void MessageDelegate(string message);
public delegate int AnotherDelegate(MyType m, long num);

A .NET-ben System.Action és System.Func a típusok általános definíciókat biztosítanak számos gyakori meghatalmazott számára. Valószínűleg nem kell új egyéni delegálási típusokat definiálnia. Ehelyett létrehozhat példányokat a megadott általános típusokról.

Az A delegate egy referenciatípus, amely egy névvel ellátott vagy névtelen metódus beágyazására használható. A meghatalmazottak hasonlóak a C++ függvénymutatóihoz; delegáltak azonban típusbiztosak és biztonságosak. A meghatalmazottak alkalmazásáról a Meghatalmazottak és az Általános meghatalmazottak című témakörben olvashat. A meghatalmazottak képezik az események alapját. A meghatalmazottak példányosíthatók úgy, hogy névvel vagy névtelen módszerrel társítják azt.

A meghatalmazottat olyan metódussal vagy lambdakifejezéssel kell példányosíteni, amely kompatibilis visszatérési típussal és bemeneti paraméterekkel rendelkezik. A metódus-aláírásban megengedett variancia mértékéről további információt a Meghatalmazottak eltérése című témakörben talál. Névtelen metódusok használata esetén a deklarált és a hozzá társítandó kód együtt lesz deklarálva.

A delegálási kombináció vagy eltávolítás futásidejű kivétellel meghiúsul, ha a futtatáskor érintett delegálási típusok eltérőek a változatkonverzió miatt. Az alábbi példa egy sikertelen helyzetet mutat be:

Action<string> stringAction = str => {};
Action<object> objectAction = obj => {};
  
// Valid due to implicit reference conversion of
// objectAction to Action<string>, but may fail
// at run time.
Action<string> combination = stringAction + objectAction;

Egy új delegált objektum létrehozásával létrehozhat egy megfelelő futtatókörnyezettípusú meghatalmazottat. Az alábbi példa bemutatja, hogyan alkalmazható ez a kerülő megoldás az előző példára.

Action<string> stringAction = str => {};
Action<object> objectAction = obj => {};
  
// Creates a new delegate instance with a runtime type of Action<string>.
Action<string> wrappedObjectAction = new Action<string>(objectAction);

// The two Action<string> delegate instances can now be combined.
Action<string> combination = stringAction + wrappedObjectAction;

Deklarálhat függvénymutatókat, amelyek hasonló szintaxist használnak. A függvénymutató az utasítást használja a calli delegált típus példányosítása és a virtuális Invoke metódus meghívása helyett.

A dinamikus típus

A dynamic típus azt jelzi, hogy a változó és a tagokra mutató hivatkozások használata megkerüli a fordítási idő típusú ellenőrzést. Ehelyett ezek a műveletek futásidőben lesznek feloldva. Ez a dynamic típus leegyszerűsíti a COM API-khoz, például az Office Automation API-khoz, a dinamikus API-khoz, például az IronPython-kódtárakhoz és a HTML-dokumentumobjektum-modellhez (DOM) való hozzáférést.

A típus dynamic a legtöbb esetben a típushoz object hasonlóan viselkedik. A nem null értékű kifejezések különösen a típusra dynamic konvertálhatók. A dynamic típus eltér attól a művelettől object , amely típuskifejezéseket dynamic tartalmaz, a fordító nem oldja fel vagy ellenőrzi a típust. A fordító a művelettel kapcsolatos információkat csomagolja össze, és ezek az információk később felhasználhatók a művelet futásidőben történő kiértékeléséhez. A folyamat részeként a típusváltozók dynamic típusváltozókká objectalakulnak. Ezért a típus dynamic csak fordítási időpontban létezik, futásidőben nem.

Az alábbi példa egy típusváltozót dynamic egy típusváltozóval objectszemben mutat be. Az egyes változók fordítási idejének ellenőrzéséhez helyezze az egérmutatót az utasítások fölé dyn vagy obj az WriteLine utasításokba. Másolja a következő kódot egy szerkesztőbe, ahol az IntelliSense elérhető. Az IntelliSense a következőhöz tartozó dinamikus és objektumokat jeleníti megobj: .dyn

class Program
{
    static void Main(string[] args)
    {
        dynamic dyn = 1;
        object obj = 1;

        // Rest the mouse pointer over dyn and obj to see their
        // types at compile time.
        System.Console.WriteLine(dyn.GetType());
        System.Console.WriteLine(obj.GetType());
    }
}

Az WriteLine utasítások a futtatási idő és a dynobj. Ezen a ponton mindkettő ugyanazzal a típussal, egész számokkal rendelkezik. A következő kimenet lesz előállítva:

System.Int32
System.Int32

A fordítási idő és obj a fordítási időpont közötti dyn különbség megtekintéséhez adja hozzá az alábbi két sort a deklarációk és az WriteLine előző példában szereplő utasítások között.

dyn = dyn + 3;
obj = obj + 3;

Egy egész szám és egy objektum kifejezésben obj + 3való hozzáadásának kísérlete esetén fordítóhiba jelenik meg. A hiba azonban nem jelenik dyn + 3meg. A benne lévő dyn kifejezés fordításkor nincs bejelölve, mert a kifejezés típusa dyn .dynamic

Az alábbi példa több deklarációban is szerepel dynamic . A Main metódus a fordítási idő típusú ellenőrzést a futásidejű típusellenőrzéssel is ellentétben állítja.

using System;

namespace DynamicExamples
{
    class Program
    {
        static void Main(string[] args)
        {
            ExampleClass ec = new ExampleClass();
            Console.WriteLine(ec.ExampleMethod(10));
            Console.WriteLine(ec.ExampleMethod("value"));

            // The following line causes a compiler error because ExampleMethod
            // takes only one argument.
            //Console.WriteLine(ec.ExampleMethod(10, 4));

            dynamic dynamic_ec = new ExampleClass();
            Console.WriteLine(dynamic_ec.ExampleMethod(10));

            // Because dynamic_ec is dynamic, the following call to ExampleMethod
            // with two arguments does not produce an error at compile time.
            // However, it does cause a run-time error.
            //Console.WriteLine(dynamic_ec.ExampleMethod(10, 4));
        }
    }

    class ExampleClass
    {
        static dynamic _field;
        dynamic Prop { get; set; }

        public dynamic ExampleMethod(dynamic d)
        {
            dynamic local = "Local variable";
            int two = 2;

            if (d is int)
            {
                return local;
            }
            else
            {
                return two;
            }
        }
    }
}
// Results:
// Local variable
// 2
// Local variable

C# nyelvspecifikáció

További információt a C# nyelvspecifikációjának alábbi szakaszaiban talál:

Lásd még