Delen via


Ingebouwde referentietypen (C#-verwijzing)

C# heeft veel ingebouwde referentietypen. Deze typen omvatten trefwoorden of operatoren die synoniemen zijn voor een type in de .NET-bibliotheek.

De C#-taalreferentiedocumenten de laatst uitgebrachte versie van de C#-taal. Het bevat ook de eerste documentatie voor functies in openbare previews voor de aanstaande taalrelease.

De documentatie identificeert alle functies die voor het eerst zijn geïntroduceerd in de laatste drie versies van de taal of in de huidige openbare previews.

Aanbeveling

Raadpleeg het artikel over de versiegeschiedenis van de C#-taal om te achterhalen wanneer een functie voor het eerst is geïntroduceerd in C#.

Het objecttype

Het object type is een alias voor System.Object in .NET. In het geïntegreerde typesysteem van C# nemen alle typen, vooraf gedefinieerde en door de gebruiker gedefinieerde, referentietypen en waardetypen direct of indirect over van System.Object. Wijs waarden van elk type toe (behalve ref struct, zie verwstruct) aan variabelen van het type object. U kunt de letterlijke waarde null toewijzen aan elke object variabele als standaardwaarde. Wanneer u een waardetypevariabele converteert naar object, wordt de waarde in het vak geplaatst. Wanneer u een variabele van het type object converteert naar een waardetype, wordt de waarde uitgeschakeld. Zie Boxing and Unboxing (Boksen en Uitpakken) voor meer informatie.

Het tekenreekstype

Het string type vertegenwoordigt een reeks van nul of meer Unicode-tekens. In .NET string is dit een alias voor System.String.

Hoewel string dit een verwijzingstype is, vergelijken de gelijkheidsoperatoren == en != vergelijkt u de waarden van string objecten, niet verwijzingen. Gelijkheid op basis van waarde maakt testen op tekenreeks gelijkheid intuïtiever. Voorbeeld:

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

In het voorgaande voorbeeld wordt 'True' en vervolgens 'False' weergegeven omdat de inhoud van de tekenreeksen gelijkwaardig is, maar ab niet naar hetzelfde tekenreeksexemplaren verwijst.

De +-operator voegt tekenreeksen samen:

string a = "good " + "morning";

Met de voorgaande code wordt een tekenreeksobject gemaakt dat 'goedemorgen' bevat.

Tekenreeksen zijn onveranderbaar . U kunt de inhoud van een tekenreeksobject niet wijzigen nadat u het hebt gemaakt. Wanneer u bijvoorbeeld deze code schrijft, maakt de compiler daadwerkelijk een nieuw tekenreeksobject voor de nieuwe reeks tekens en wijst het nieuwe object toe aan b. Het toegewezen geheugen b voor (wanneer deze de tekenreeks 'h' bevat), komt vervolgens in aanmerking voor garbagecollection.

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

U kunt de []operator gebruiken voor leestoegang tot afzonderlijke tekens van een tekenreeks. Geldige indexwaarden beginnen bij 0 en moeten kleiner zijn dan de lengte van de tekenreeks:

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

Op dezelfde manier kunt u de [] operator gebruiken om elk teken in een tekenreeks te herhalen:

string str = "test";

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

Letterlijke tekenreeksen

Letterlijke tekenreeksen zijn van het type string en komen in drie vormen voor: onbewerkt, aanhalingstekens en exacte bewoordingen.

Letterlijke tekenreeksen van onbewerkte tekenreeksen bevatten willekeurige tekst zonder escapereeksen. Letterlijke tekenreeksen voor onbewerkte tekenreeksen kunnen witruimte en nieuwe regels, ingesloten aanhalingstekens en andere speciale tekens bevatten. Letterlijke tekenreeksen van onbewerkte tekenreeksen staan tussen minimaal drie dubbele aanhalingstekens ("""):

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

U kunt zelfs een reeks van drie (of meer) dubbele aanhalingstekens opnemen. Als voor uw tekst een ingesloten reeks aanhalingstekens is vereist, begint en beëindigt u de letterlijke tekenreeks met meer aanhalingstekens, indien nodig:

"""""
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.
"""""

Letterlijke tekenreeksen voor onbewerkte tekenreeksen hebben doorgaans de begin- en eindvolgordes voor aanhalingstekens op afzonderlijke regels van de ingesloten tekst. Letterlijke tekenreeksen met meerdere regels ondersteunen tekenreeksen die zelf tekenreeksen tussen aanhaalt:

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

Wanneer de begin- en eindophalingstekens op afzonderlijke regels staan, worden de nieuwe regels na de aanhalingstekens en voorafgaande aan de eindcitaat niet opgenomen in de uiteindelijke inhoud. De reeks aanhalingstekens sluiten bepaalt de meest linkse kolom voor de letterlijke tekenreeks. U kunt een letterlijke onbewerkte tekenreeks laten inspringen zodat deze overeenkomt met de algemene code-indeling:

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

Kolommen rechts van de eindopgavevolgorde blijven behouden. Dit gedrag maakt onbewerkte tekenreeksen mogelijk voor gegevensindelingen zoals JSON, YAML of XML, zoals wordt weergegeven in het volgende voorbeeld:

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

Aanbeveling

Visual Studio en de C# Dev Kit bieden validatie- en syntaxismarkeringen wanneer letterlijke tekenreeksen JSON-gegevens of reguliere expressies bevatten.

De hulpprogramma's parseren de tekst. Als de hulpprogramma's er vertrouwen in hebben dat de tekst JSON of een reguliere expressie vertegenwoordigt, biedt de editor syntaxiskleuring.

U kunt deze ervaring verbeteren door een opmerking toe te voegen boven de declaratie die de notatie aangeeft:

  • // lang=json geeft aan dat de letterlijke tekenreeks JSON-gegevens vertegenwoordigt.
  • // lang=regex geeft aan dat de letterlijke onbewerkte tekenreeks een reguliere expressie vertegenwoordigt.

Wanneer een letterlijke tekenreeks wordt gebruikt als argument waarbij de parameter de System.Diagnostics.CodeAnalysis.StringSyntaxAttribute notatie aangeeft, valideren deze hulpprogramma's de letterlijke letterlijke tekenreeks voor sommige indelingstypen. Zowel JSON als regex worden ondersteund.

Voor sommige indelingen biedt de opmerking of het kenmerk codesuggesties oplossingen voor letterlijke tekenreeksen op basis van de indeling.

De compiler retourneert een fout als een van de tekstregels links van de afsluitende aanhalingstekenreeks wordt uitgebreid. De aanhalingstekenreeksen voor openen en sluiten kunnen zich op dezelfde regel bevinden, zodat de letterlijke tekenreeks van de tekenreeks niet begint of eindigt met een aanhalingsteken:

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

U kunt letterlijke tekenreeksen combineren met tekenreeksinterpolatie om aanhalingstekens en accolades in de uitvoertekenreeks op te nemen.

Letterlijke tekenreeks tussen aanhalingstekens tussen dubbele aanhalingstekens ("):

"good morning"  // a string literal

Letterlijke tekenreeksen kunnen elke letterlijke tekenreeks bevatten. Escape-reeksen zijn opgenomen. In het volgende voorbeeld wordt een escape-reeks \\ gebruikt voor backslash, \u0066 voor de letter f en \n voor newline.

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

Notitie

De escapecode \udddd (waarbij dddd een getal van vier cijfers is) vertegenwoordigt het Unicode-teken U+dddd. Unicode-escapecodes met acht cijfers worden ook herkend: \Udddddddd.

geplaatst. Voorbeeld:

@"good morning"  // a string literal

Het voordeel van verbatimtekenreeksen is dat escapereeksen niet worden verwerkt, waardoor ze eenvoudig kunnen worden geschreven. De volgende tekst komt bijvoorbeeld overeen met een volledig gekwalificeerde Windows-bestandsnaam:

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

Als u een dubbel aanhalingsteken wilt opnemen in een tekenreeks met @aanhalingstekens, dubbelt u het volgende:

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

Letterlijke tekenreeksen van UTF-8

.NET slaat tekenreeksen op met behulp van UTF-16-codering. UTF-8 is de standaard voor webprotocollen en andere belangrijke bibliotheken. U kunt het u8 achtervoegsel toevoegen aan een letterlijke tekenreeks om UTF-8-codering op te geven. De compiler slaat UTF-8 letterlijke waarden op als ReadOnlySpan<byte> objecten. Als u een letterlijke UTF-8-tekenreeks gebruikt, wordt een duidelijkere declaratie gemaakt dan het equivalent System.ReadOnlySpan<T>te declareren, zoals wordt weergegeven in de volgende code:

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

Als u een letterlijke UTF-8-tekenreeks als matrix wilt opslaan, kopieert ReadOnlySpan<T>.ToArray() u de bytes met de letterlijke waarde naar de onveranderbare matrix:

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

Letterlijke waarden voor UTF-8-tekenreeksen zijn geen compilatietijdconstanten; het zijn runtimeconstanten. Daarom kunnen ze niet worden gebruikt als de standaardwaarde voor een optionele parameter. U kunt letterlijke tekenreeksen van UTF-8 niet combineren met tekenreeksinterpolatie. U kunt het $ token en het u8 achtervoegsel niet gebruiken voor dezelfde tekenreeksexpressie.

Het type gemachtigde

De declaratie van een type gemachtigde is vergelijkbaar met een methodehandtekening. Het heeft een retourwaarde en een willekeurig aantal parameters van elk type:

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

In .NET System.Action bieden typen System.Func algemene definities voor veel algemene gemachtigden. Waarschijnlijk hoeft u geen nieuwe aangepaste gedelegeerdentypen te definiëren. In plaats daarvan kunt u instantiëringen maken van de opgegeven algemene typen.

Een delegate is een ingebouwd referentietype dat u kunt gebruiken om een benoemde of anonieme methode in te kapselen. Gemachtigden zijn vergelijkbaar met functiepointers in C++; Gemachtigden zijn echter type-veilig en veilig. Zie Gemachtigden en Algemene gemachtigden voor toepassingen van gemachtigden. Gemachtigden vormen de basis voor gebeurtenissen. U instantieert een gemachtigde door deze te koppelen aan een benoemde of anonieme methode.

U moet de gemachtigde instantiëren met een methode of lambda-expressie met een compatibel retourtype en invoerparameters. Zie Afwijking in Gemachtigden voor meer informatie over de mate van variantie die is toegestaan in de handtekening van de methode. Voor gebruik met anonieme methoden declareert u de gemachtigde en de code die eraan moet worden gekoppeld.

De combinatie of verwijdering van gemachtigden mislukt met een runtime-uitzondering wanneer de gedelegeerdentypen die tijdens de uitvoering zijn betrokken, verschillen vanwege variantconversie. In het volgende voorbeeld ziet u een situatie die mislukt:

Action<string> stringAction = str => {};
Action<object> objectAction = obj => {};

// Valid due to implicit reference conversion of
// objectAction to Action<string>, but might fail
// at run time.
Action<string> combination = stringAction + objectAction;

U kunt een gemachtigde maken met het juiste runtimetype door een nieuw gedelegeerde-object te maken. In het volgende voorbeeld ziet u hoe deze tijdelijke oplossing kan worden toegepast op het voorgaande voorbeeld.

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;

U kunt functie-aanwijzers declareren, die vergelijkbare syntaxis gebruiken. Een functiepointer gebruikt de calli instructie in plaats van een gemachtigde te instantiëren en de virtuele Invoke methode aan te roepen.

Het dynamische type

Het dynamic type geeft aan dat de variabele en verwijzingen naar de leden de controle van het type compileertijd overslaan. In plaats daarvan worden deze bewerkingen tijdens runtime opgelost. Het dynamic type vereenvoudigt de toegang tot COM-API's, zoals de Office Automation-API's, tot dynamische API's zoals IronPython-bibliotheken en het HTML Document Object Model (DOM).

Type dynamic gedraagt zich als het type object in de meeste omstandigheden. Met name elke niet-null-expressie kan worden geconverteerd naar het dynamic type. Het dynamic type wijkt af van object dat de compiler geen bewerkingen voor het oplossen of typen van controles bevat die expressies van het type dynamicbevatten. De compiler verpakt informatie over de bewerking en die informatie wordt later gebruikt om de bewerking tijdens runtime te evalueren. Als onderdeel van het proces worden variabelen van het type dynamic gecompileerd in variabelen van het type object. Daarom bestaat het type dynamic alleen tijdens het compileren, niet tijdens runtime.

In het volgende voorbeeld wordt een variabele van het type dynamic met een variabele van het type objectcontrast weergegeven. Als u het type van elke variabele tijdens het compileren wilt controleren, plaatst u de muiswijzer op dyn of obj in de WriteLine instructies. Kopieer de volgende code naar een editor waar IntelliSense beschikbaar is. IntelliSense toont dynamisch voor dyn en object voor obj.

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());
    }
}

In WriteLine de instructies worden de runtimetypen dyn en obj. Op dat moment hebben beide hetzelfde type, geheel getal. De volgende uitvoer wordt geproduceerd:

System.Int32
System.Int32

Als u het verschil tussen dyn en obj tijdens het compileren wilt zien, voegt u de volgende twee regels toe tussen de declaraties en de WriteLine instructies in het vorige voorbeeld.

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

Er wordt een compilerfout gerapporteerd voor het toevoegen van een geheel getal en een object in expressie obj + 3. Er wordt echter geen fout gerapporteerd voor dyn + 3. De expressie die bevat dyn , wordt niet gecontroleerd tijdens het compileren omdat het type dyn is dynamic.

In het volgende voorbeeld worden verschillende declaraties gebruikt dynamic . De Main methode contrasteert ook het controleren van het type compileertijd met het controleren van runtime-typen.

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#-taalspecificatie

Zie de volgende secties van de C#-taalspecificatie voor meer informatie:

Zie ook