Vanligt typsystem
Det gemensamma typsystemet definierar hur typer deklareras, används och hanteras i den gemensamma språkkörningen och är också en viktig del av körningens stöd för integrering mellan språk. Det vanliga typsystemet utför följande funktioner:
Upprättar ett ramverk som hjälper till att möjliggöra integrering mellan språk, typsäkerhet och kodkörning med höga prestanda.
Tillhandahåller en objektorienterad modell som stöder fullständig implementering av många programmeringsspråk.
Definierar regler som språk måste följa, vilket hjälper till att säkerställa att objekt som skrivs på olika språk kan interagera med varandra.
Innehåller ett bibliotek som innehåller de primitiva datatyper (till exempel , Byte, Char, Int32och UInt64) som Booleananvänds i programutveckling.
Typer i .NET
Alla typer i .NET är antingen värdetyper eller referenstyper.
Värdetyper är datatyper vars objekt representeras av objektets faktiska värde. Om en instans av en värdetyp tilldelas till en variabel får den variabeln en ny kopia av värdet.
Referenstyper är datatyper vars objekt representeras av en referens (liknar en pekare) till objektets faktiska värde. Om en referenstyp tilldelas till en variabel refererar variabeln till (pekar på) det ursprungliga värdet. Ingen kopia görs.
Det vanliga typsystemet i .NET stöder följande fem typer:
Klasser
En klass är en referenstyp som kan härledas direkt från en annan klass och som härleds implicit från System.Object. Klassen definierar de åtgärder som ett objekt (som är en instans av klassen) kan utföra (metoder, händelser eller egenskaper) och de data som objektet innehåller (fält). Även om en klass vanligtvis innehåller både definition och implementering (till skillnad från gränssnitt, till exempel som endast innehåller definition utan implementering), kan den ha en eller flera medlemmar som inte har någon implementering.
I följande tabell beskrivs några av de egenskaper som en klass kan ha. Varje språk som stöder körningen ger ett sätt att ange att en klass- eller klassmedlem har en eller flera av dessa egenskaper. Enskilda programmeringsspråk som är avsedda för .NET kanske inte gör alla dessa egenskaper tillgängliga.
Characteristic | beskrivning |
---|---|
stängd | Anger att en annan klass inte kan härledas från den här typen. |
Implementerar | Anger att klassen använder ett eller flera gränssnitt genom att tillhandahålla implementeringar av gränssnittsmedlemmar. |
abstrakt | Anger att klassen inte kan instansieras. Om du vill använda den måste du härleda en annan klass från den. |
Ärver | Anger att instanser av klassen kan användas var som helst där basklassen har angetts. En härledd klass som ärver från en basklass kan använda implementeringen av alla offentliga medlemmar som tillhandahålls av basklassen, eller så kan den härledda klassen åsidosätta implementeringen av de offentliga medlemmarna med sin egen implementering. |
exporteras eller inte exporteras | Anger om en klass visas utanför sammansättningen där den definieras. Den här egenskapen gäller endast för toppklasser och inte för kapslade klasser. |
Kommentar
En klass kan också kapslas i en överordnad klass eller struktur. Kapslade klasser har också medlemsegenskaper. Mer information finns i Kapslade typer.
Klassmedlemmar som inte har någon implementering är abstrakta medlemmar. En klass som har en eller flera abstrakta medlemmar är i sig abstrakt. det går inte att skapa nya instanser av den. Med vissa språk som är inriktade på körningen kan du markera en klass som abstrakt även om ingen av dess medlemmar är abstrakta. Du kan använda en abstrakt klass när du vill kapsla in en grundläggande uppsättning funktioner som härledda klasser kan ärva eller åsidosätta när det är lämpligt. Klasser som inte är abstrakta kallas för betongklasser.
En klass kan implementera valfritt antal gränssnitt, men den kan bara ärva från en basklass utöver System.Object, från vilken alla klasser ärver implicit. Alla klasser måste ha minst en konstruktor, vilket initierar nya instanser av klassen. Om du inte uttryckligen definierar en konstruktor tillhandahåller de flesta kompilatorer automatiskt en parameterlös konstruktor.
Strukturer
En struktur är en värdetyp som härleds implicit från System.ValueType, som i sin tur härleds från System.Object. En struktur är användbar för att representera värden vars minnesbehov är små och för att skicka värden som bivärdesparametrar till metoder som har starkt skrivna parametrar. I .NET definieras alla primitiva datatyper (Boolean, , CharByte, DateTime, Decimal, Double, Int16, Int64Int32, SByte, Single, UInt16, UInt32och UInt64) som strukturer.
Precis som klasser definierar strukturer både data (strukturens fält) och de åtgärder som kan utföras på dessa data (strukturens metoder). Det innebär att du kan anropa metoder för strukturer, inklusive de virtuella metoder som definierats för System.Object klasserna och System.ValueType och alla metoder som definierats på själva värdetypen. Strukturer kan med andra ord ha fält, egenskaper och händelser samt statiska och icke-statiska metoder. Du kan skapa instanser av strukturer, skicka dem som parametrar, lagra dem som lokala variabler eller lagra dem i ett fält med en annan värdetyp eller referenstyp. Strukturer kan också implementera gränssnitt.
Värdetyper skiljer sig också från klasser i flera avseenden. För det första, även om de implicit ärver från System.ValueType, kan de inte ärva direkt från någon typ. På samma sätt är alla värdetyper förseglade, vilket innebär att ingen annan typ kan härledas från dem. De kräver inte heller konstruktorer.
För varje värdetyp tillhandahåller common language runtime en motsvarande boxad typ, vilket är en klass som har samma tillstånd och beteende som värdetypen. En instans av en värdetyp boxas när den skickas till en metod som accepterar en parameter av typen System.Object. Den är oboxad (det vill säga konverteras från en instans av en klass tillbaka till en instans av en värdetyp) när kontrollen returneras från ett metodanrop som accepterar en värdetyp som en bireferensparameter. Vissa språk kräver att du använder särskild syntax när den boxade typen krävs. andra använder automatiskt den boxade typen när den behövs. När du definierar en värdetyp definierar du både den boxade och den oboxade typen.
Uppräkningar
En uppräkning är en värdetyp som ärver direkt från System.Enum och som tillhandahåller alternativa namn för värdena för en underliggande primitiv typ. En uppräkningstyp har ett namn, en underliggande typ som måste vara en av de inbyggda signerade eller osignerade heltalstyperna (till exempel Byte, Int32eller UInt64) och en uppsättning fält. Fälten är statiska literalfält, som var och en representerar en konstant. Samma värde kan tilldelas till flera fält. När detta inträffar måste du markera ett av värdena som det primära uppräkningsvärdet för reflektion och strängkonvertering.
Du kan tilldela ett värde av den underliggande typen till en uppräkning och vice versa (ingen gjutning krävs av körningen). Du kan skapa en instans av en uppräkning och anropa metoderna System.Enumför , samt alla metoder som definierats för uppräkningens underliggande typ. Men vissa språk kanske inte låter dig skicka en uppräkning som en parameter när en instans av den underliggande typen krävs (eller vice versa).
Följande ytterligare begränsningar gäller för uppräkningar:
De kan inte definiera sina egna metoder.
De kan inte implementera gränssnitt.
De kan inte definiera egenskaper eller händelser.
De kan inte vara generiska, såvida de inte bara är generiska eftersom de är kapslade inom en allmän typ. En uppräkning kan alltså inte ha egna typparametrar.
Kommentar
Kapslade typer (inklusive uppräkningar) som skapats med Visual Basic, C#och C++ innehåller typparametrarna för alla omslutande generiska typer och är därför generiska även om de inte har egna typparametrar. Mer information finns i "Kapslade typer" i referensavsnittet Type.MakeGenericType .
Attributet FlagsAttribute anger en särskild typ av uppräkning som kallas bitfält. Själva körningen skiljer inte mellan traditionella uppräkningar och bitfält, men ditt språk kan göra det. När den här skillnaden görs kan bitvis operatorer användas på bitfält, men inte på uppräkningar, för att generera namnlösa värden. Uppräkningar används vanligtvis för listor över unika element, till exempel veckodagar, namn på land eller region och så vidare. Bitfält används vanligtvis för listor över kvaliteter eller kvantiteter som kan förekomma i kombination, till exempel Red And Big And Fast
.
I följande exempel visas hur du använder både bitfält och traditionella uppräkningar.
using System;
using System.Collections.Generic;
// A traditional enumeration of some root vegetables.
public enum SomeRootVegetables
{
HorseRadish,
Radish,
Turnip
}
// A bit field or flag enumeration of harvesting seasons.
[Flags]
public enum Seasons
{
None = 0,
Summer = 1,
Autumn = 2,
Winter = 4,
Spring = 8,
All = Summer | Autumn | Winter | Spring
}
public class Example
{
public static void Main()
{
// Hash table of when vegetables are available.
Dictionary<SomeRootVegetables, Seasons> AvailableIn = new Dictionary<SomeRootVegetables, Seasons>();
AvailableIn[SomeRootVegetables.HorseRadish] = Seasons.All;
AvailableIn[SomeRootVegetables.Radish] = Seasons.Spring;
AvailableIn[SomeRootVegetables.Turnip] = Seasons.Spring |
Seasons.Autumn;
// Array of the seasons, using the enumeration.
Seasons[] theSeasons = new Seasons[] { Seasons.Summer, Seasons.Autumn,
Seasons.Winter, Seasons.Spring };
// Print information of what vegetables are available each season.
foreach (Seasons season in theSeasons)
{
Console.Write(String.Format(
"The following root vegetables are harvested in {0}:\n",
season.ToString("G")));
foreach (KeyValuePair<SomeRootVegetables, Seasons> item in AvailableIn)
{
// A bitwise comparison.
if (((Seasons)item.Value & season) > 0)
Console.Write(String.Format(" {0:G}\n",
(SomeRootVegetables)item.Key));
}
}
}
}
// The example displays the following output:
// The following root vegetables are harvested in Summer:
// HorseRadish
// The following root vegetables are harvested in Autumn:
// Turnip
// HorseRadish
// The following root vegetables are harvested in Winter:
// HorseRadish
// The following root vegetables are harvested in Spring:
// Turnip
// Radish
// HorseRadish
Imports System.Collections.Generic
' A traditional enumeration of some root vegetables.
Public Enum SomeRootVegetables
HorseRadish
Radish
Turnip
End Enum
' A bit field or flag enumeration of harvesting seasons.
<Flags()> Public Enum Seasons
None = 0
Summer = 1
Autumn = 2
Winter = 4
Spring = 8
All = Summer Or Autumn Or Winter Or Spring
End Enum
' Entry point.
Public Class Example
Public Shared Sub Main()
' Hash table of when vegetables are available.
Dim AvailableIn As New Dictionary(Of SomeRootVegetables, Seasons)()
AvailableIn(SomeRootVegetables.HorseRadish) = Seasons.All
AvailableIn(SomeRootVegetables.Radish) = Seasons.Spring
AvailableIn(SomeRootVegetables.Turnip) = Seasons.Spring Or _
Seasons.Autumn
' Array of the seasons, using the enumeration.
Dim theSeasons() As Seasons = {Seasons.Summer, Seasons.Autumn, _
Seasons.Winter, Seasons.Spring}
' Print information of what vegetables are available each season.
For Each season As Seasons In theSeasons
Console.WriteLine(String.Format( _
"The following root vegetables are harvested in {0}:", _
season.ToString("G")))
For Each item As KeyValuePair(Of SomeRootVegetables, Seasons) In AvailableIn
' A bitwise comparison.
If (CType(item.Value, Seasons) And season) > 0 Then
Console.WriteLine(" " + _
CType(item.Key, SomeRootVegetables).ToString("G"))
End If
Next
Next
End Sub
End Class
' The example displays the following output:
' The following root vegetables are harvested in Summer:
' HorseRadish
' The following root vegetables are harvested in Autumn:
' Turnip
' HorseRadish
' The following root vegetables are harvested in Winter:
' HorseRadish
' The following root vegetables are harvested in Spring:
' Turnip
' Radish
' HorseRadish
Gränssnitt
Ett gränssnitt definierar ett kontrakt som anger en "kan göra"-relation eller en "har en" relation. Gränssnitt används ofta för att implementera funktioner, till exempel att jämföra och sortera (gränssnitten IComparable och IComparable<T> ), testa för likhet ( IEquatable<T> gränssnittet) eller räkna upp objekt i en samling (gränssnitten IEnumerable och IEnumerable<T> ). Gränssnitt kan ha egenskaper, metoder och händelser, som alla är abstrakta medlemmar. Det innebär att även om gränssnittet definierar medlemmarna och deras signaturer, lämnar det det till den typ som implementerar gränssnittet för att definiera funktionaliteten för varje gränssnittsmedlem. Det innebär att alla klasser eller strukturer som implementerar ett gränssnitt måste tillhandahålla definitioner för de abstrakta medlemmar som deklareras i gränssnittet. Ett gränssnitt kan kräva att alla implementeringsklasser eller strukturer implementerar ett eller flera andra gränssnitt.
Följande begränsningar gäller för gränssnitt:
- Ett gränssnitt kan deklareras med alla hjälpmedel, men alla gränssnittsmedlemmar måste ha offentlig tillgänglighet.
- Gränssnitt kan inte definiera konstruktorer.
- Gränssnitt kan inte definiera fält.
- Gränssnitt kan bara definiera instansmedlemmar. De kan inte definiera statiska medlemmar.
Varje språk måste tillhandahålla regler för att mappa en implementering till det gränssnitt som kräver medlemmen, eftersom mer än ett gränssnitt kan deklarera en medlem med samma signatur, och dessa medlemmar kan ha separata implementeringar.
Delegeringar
Ombud är referenstyper som har ett syfte som liknar funktionspekare i C++. De används för händelsehanterare och återanropsfunktioner i .NET. Till skillnad från funktionspekare är ombud säkra, verifierbara och typsäkra. En ombudstyp kan representera valfri instansmetod eller statisk metod som har en kompatibel signatur.
En parameter för ett ombud är kompatibel med motsvarande parameter för en metod om typen av delegatparameter är mer restriktiv än typen av metodparameter, eftersom detta garanterar att ett argument som skickas till ombudet kan skickas på ett säkert sätt till metoden.
På samma sätt är returtypen för ett ombud kompatibel med returtypen för en metod om returtypen för metoden är mer restriktiv än ombudets returtyp, eftersom detta garanterar att returvärdet för metoden kan överföras på ett säkert sätt till ombudets returtyp.
Ett ombud som till exempel har en parameter av typen IEnumerable och en returtyp Object kan representera en metod som har en parameter av typen Object och ett returvärde av typen IEnumerable. Mer information och exempelkod finns i Delegate.CreateDelegate(Type, Object, MethodInfo).
Ett ombud sägs vara bundet till den metod som den representerar. Förutom att vara bunden till metoden kan ett ombud bindas till ett objekt. Objektet representerar den första parametern i metoden och skickas till metoden varje gång ombudet anropas. Om metoden är en instansmetod skickas det bundna objektet som implicit this
parameter (Me
i Visual Basic); om metoden är statisk skickas objektet som den första formella parametern för metoden och ombudssignaturen måste matcha de återstående parametrarna. Mer information och exempelkod finns i System.Delegate.
Alla ombud ärver från System.MulticastDelegate, som ärver från System.Delegate. Språken C#, Visual Basic och C++ tillåter inte arv från dessa typer. I stället tillhandahåller de nyckelord för att deklarera ombud.
Eftersom ombud ärver från MulticastDelegatehar ett ombud en anropslista, som är en lista över metoder som ombudet representerar och som körs när ombudet anropas. Alla metoder i listan tar emot de argument som anges när ombudet anropas.
Kommentar
Returvärdet definieras inte för ett ombud som har mer än en metod i listan över anrop, även om ombudet har en returtyp.
I många fall, till exempel med motringningsmetoder, representerar ett ombud bara en metod, och de enda åtgärder du behöver vidta är att skapa ombudet och anropa det.
För ombud som representerar flera metoder tillhandahåller .NET metoder för Delegate och MulticastDelegate delegerar klasser för att stödja åtgärder, till exempel att lägga till en metod i en delegats anropslista ( Delegate.Combine metoden), ta bort en metod ( Delegate.Remove metoden) och hämta listan över anrop ( Delegate.GetInvocationList metoden).
Kommentar
Det är inte nödvändigt att använda dessa metoder för händelsehanterardelegater i C#, C++ och Visual Basic, eftersom dessa språk ger syntax för att lägga till och ta bort händelsehanterare.
Typdefinitioner
En typdefinition innehåller följande:
- Alla attribut som definierats för typen.
- Typens hjälpmedel (synlighet).
- Typens namn.
- Typens bastyp.
- Alla gränssnitt som implementeras av typen .
- Definitioner för var och en av typens medlemmar.
Attribut
Attribut ger ytterligare användardefinierade metadata. Oftast används de för att lagra ytterligare information om en typ i dess sammansättning, eller för att ändra beteendet för en typmedlem i antingen design-time- eller körningsmiljön.
Attribut är själva klasser som ärver från System.Attribute. Språk som stöder användning av attribut har var och en sin egen syntax för att tillämpa attribut på ett språkelement. Attribut kan tillämpas på nästan alla språkelement. de specifika element som ett attribut kan tillämpas på definieras av AttributeUsageAttribute det som tillämpas på den attributklassen.
Skriv hjälpmedel
Alla typer har en modifierare som styr deras tillgänglighet från andra typer. I följande tabell beskrivs de typåtkomstfunktioner som stöds av körningen.
Tillgänglighet | beskrivning |
---|---|
offentligt | Typen är tillgänglig för alla sammansättningar. |
sammansättning | Typen är endast tillgänglig inifrån dess sammansättning. |
Tillgängligheten för en kapslad typ beror på dess tillgänglighetsdomän, vilket bestäms av både medlemmens deklarerade tillgänglighet och tillgänglighetsdomänen för den omedelbart innehållande typen. Tillgänglighetsdomänen för en kapslad typ får dock inte överskrida den som innehåller typen.
Tillgänglighetsdomänen för en kapslad medlem M
som deklareras i en typ T
i ett program P
definieras på följande sätt (notera att det M
kan vara en typ):
Om den deklarerade tillgängligheten
M
för ärpublic
är tillgänglighetsdomänenM
för tillgänglighetsdomänenT
för .Om den deklarerade tillgängligheten
M
för ärprotected internal
är tillgänglighetsdomänenM
för skärningspunkten för tillgänglighetsdomänenT
med programtextenP
i och programtexten av alla typer som härletts frånT
deklarerade utanförP
.Om den deklarerade tillgängligheten för är
protected
är tillgänglighetsdomänenM
i skärningspunkten för tillgänglighetsdomänenT
med programtexten avT
och alla typer som härletts frånT
.M
Om den deklarerade tillgängligheten
M
för ärinternal
är tillgänglighetsdomänenM
i skärningspunkten för tillgänglighetsdomänenT
för med programtextenP
i .Om den deklarerade tillgängligheten
M
för ärprivate
är tillgänglighetsdomänenM
för programtextenT
i .
Typnamn
Det gemensamma typsystemet tillämpar endast två begränsningar för namn:
- Alla namn kodas som strängar med Unicode-tecken (16 bitar).
- Namn får inte ha ett inbäddat (16-bitars) värde för 0x0000.
De flesta språk har dock ytterligare begränsningar för typnamn. Alla jämförelser görs på byte-by-byte-basis och är därför skiftlägeskänsliga och nationella oberoende.
Även om en typ kan referera till typer från andra moduler och sammansättningar, måste en typ vara helt definierad i en .NET-modul. (Beroende på stöd för kompilatorn kan den dock delas upp i flera källkodsfiler.) Typnamn behöver bara vara unika inom ett namnområde. För att fullständigt identifiera en typ måste typnamnet kvalificeras av namnområdet som innehåller implementeringen av typen.
Bastyper och gränssnitt
En typ kan ärva värden och beteenden från en annan typ. Det vanliga typsystemet tillåter inte att typer ärver från mer än en bastyp.
En typ kan implementera valfritt antal gränssnitt. För att implementera ett gränssnitt måste en typ implementera alla virtuella medlemmar i gränssnittet. En virtuell metod kan implementeras av en härledd typ och kan anropas statiskt eller dynamiskt.
Skriv medlemmar
Med körningen kan du definiera medlemmar av din typ, vilket anger beteendet och tillståndet för en typ. Typmedlemmar innehåller följande:
Fält
Ett fält beskriver och innehåller en del av typens tillstånd. Fält kan vara av valfri typ som stöds av körningen. Oftast är fält antingen private
eller protected
, så att de endast är tillgängliga från klassen eller från en härledd klass. Om värdet för ett fält kan ändras utanför dess typ används vanligtvis en egenskapsuppsättningsåtkomstor. Offentligt exponerade fält är vanligtvis skrivskyddade och kan vara av två typer:
- Konstanter, vars värde tilldelas vid designtillfället. Dessa är statiska medlemmar i en klass, även om de inte definieras med nyckelordet
static
(Shared
i Visual Basic). - Skrivskyddade variabler, vars värden kan tilldelas i klasskonstruktorn.
I följande exempel visas dessa två användningar av skrivskyddade fält.
using System;
public class Constants
{
public const double Pi = 3.1416;
public readonly DateTime BirthDate;
public Constants(DateTime birthDate)
{
this.BirthDate = birthDate;
}
}
public class Example
{
public static void Main()
{
Constants con = new Constants(new DateTime(1974, 8, 18));
Console.Write(Constants.Pi + "\n");
Console.Write(con.BirthDate.ToString("d") + "\n");
}
}
// The example displays the following output if run on a system whose current
// culture is en-US:
// 3.1416
// 8/18/1974
Public Class Constants
Public Const Pi As Double = 3.1416
Public ReadOnly BirthDate As Date
Public Sub New(birthDate As Date)
Me.BirthDate = birthDate
End Sub
End Class
Public Module Example
Public Sub Main()
Dim con As New Constants(#8/18/1974#)
Console.WriteLine(Constants.Pi.ToString())
Console.WriteLine(con.BirthDate.ToString("d"))
End Sub
End Module
' The example displays the following output if run on a system whose current
' culture is en-US:
' 3.1416
' 8/18/1974
Egenskaper
En egenskap namnger ett värde eller tillstånd av typen och definierar metoder för att hämta eller ange egenskapens värde. Egenskaper kan vara primitiva typer, samlingar av primitiva typer, användardefinierade typer eller samlingar av användardefinierade typer. Egenskaper används ofta för att hålla det offentliga gränssnittet av en typ oberoende av typens faktiska representation. Detta gör det möjligt för egenskaper att återspegla värden som inte lagras direkt i klassen (till exempel när en egenskap returnerar ett beräknat värde) eller att utföra validering innan värden tilldelas till privata fält. I följande exempel visas det senare mönstret.
using System;
public class Person
{
private int m_Age;
public int Age
{
get { return m_Age; }
set {
if (value < 0 || value > 125)
{
throw new ArgumentOutOfRangeException("The value of the Age property must be between 0 and 125.");
}
else
{
m_Age = value;
}
}
}
}
Public Class Person
Private m_Age As Integer
Public Property Age As Integer
Get
Return m_Age
End Get
Set
If value < 0 Or value > 125 Then
Throw New ArgumentOutOfRangeException("The value of the Age property must be between 0 and 125.")
Else
m_Age = value
End If
End Set
End Property
End Class
Förutom att inkludera själva egenskapen innehåller det gemensamma mellanliggande språket (CIL) för en typ som innehåller en läsbar egenskap en get_
egenskapsnamnsmetod , och CIL för en typ som innehåller en skrivbar egenskap innehåller en set_
egenskapsnamnsmetod .
Metoder
En metod beskriver åtgärder som är tillgängliga för typen. En metods signatur anger de tillåtna typerna av alla dess parametrar och dess returvärde.
Även om de flesta metoder definierar det exakta antalet parametrar som krävs för metodanrop stöder vissa metoder ett variabelt antal parametrar. Den slutliga deklarerade parametern för dessa metoder markeras med attributet ParamArrayAttribute . Språkkompilatorer tillhandahåller vanligtvis ett nyckelord, till exempel params
i C# och ParamArray
i Visual Basic, som gör explicit användning av ParamArrayAttribute onödig.
Konstruktorer
En konstruktor är en speciell typ av metod som skapar nya instanser av en klass eller struktur. Precis som med andra metoder kan en konstruktor innehålla parametrar. Konstruktorer har dock inget returvärde (det vill: de returnerar void
).
Om källkoden för en klass inte uttryckligen definierar en konstruktor innehåller kompilatorn en parameterlös konstruktor. Men om källkoden för en klass endast definierar parametriserade konstruktorer genererar kompilatorerna Visual Basic och C# inte en parameterlös konstruktor.
Om källkoden för en struktur definierar konstruktorer måste de parametriseras. En struktur kan inte definiera en parameterlös konstruktor och kompilatorer genererar inte parameterlösa konstruktorer för strukturer eller andra värdetyper. Alla värdetyper har en implicit parameterlös konstruktor. Den här konstruktorn implementeras av den gemensamma språkkörningen och initierar alla fält i strukturen till deras standardvärden.
Händelser
En händelse definierar en incident som kan besvaras och definierar metoder för att prenumerera på, avprenumerera från och höja händelsen. Händelser används ofta för att informera andra typer av tillståndsändringar. Mer information finns i Händelser.
Kapslade typer
En kapslad typ är en typ som är medlem av någon annan typ. Kapslade typer bör vara nära kopplade till sin innehållande typ och får inte vara användbara som en generell typ. Kapslade typer är användbara när deklareringstypen använder och skapar instanser av den kapslade typen, och användningen av den kapslade typen inte exponeras i offentliga medlemmar.
Kapslade typer är förvirrande för vissa utvecklare och bör inte vara offentligt synliga om det inte finns en övertygande anledning till synlighet. I ett väldesignat bibliotek bör utvecklare sällan behöva använda kapslade typer för att instansiera objekt eller deklarera variabler.
Egenskaper för typmedlemmar
Det gemensamma typsystemet gör det möjligt för typmedlemmar att ha en mängd olika egenskaper. Språk krävs dock inte för att stödja alla dessa egenskaper. I följande tabell beskrivs medlemsegenskaper.
Characteristic | Kan gälla för | beskrivning |
---|---|---|
abstrakt | Metoder, egenskaper och händelser | Typen anger inte metodens implementering. Typer som ärver eller implementerar abstrakta metoder måste tillhandahålla en implementering för metoden. Det enda undantaget är när den härledda typen i sig är en abstrakt typ. Alla abstrakta metoder är virtuella. |
privat, familj, församling, familj och församling, familj eller församling eller offentlig | Alla | Definierar tillgängligheten för medlemmen: privat Endast tillgänglig från samma typ som medlemmen eller inom en kapslad typ. familj Tillgänglig från samma typ som medlemmen och från härledda typer som ärver från den. sammansättning Endast tillgängligt i sammansättningen där typen har definierats. familj och sammansättning Endast tillgänglig från typer som är kvalificerade för både familje- och sammansättningsåtkomst. familj eller sammansättning Endast tillgänglig från typer som är kvalificerade för antingen familje- eller sammansättningsåtkomst. offentligt Tillgänglig från valfri typ. |
sist | Metoder, egenskaper och händelser | Den virtuella metoden kan inte åsidosättas i en härledd typ. |
initiera endast | Fält | Värdet kan bara initieras och kan inte skrivas efter initieringen. |
instans | Fält, metoder, egenskaper och händelser | Om en medlem inte har markerats som static (C# och C++), Shared (Visual Basic), virtual (C# och C++) eller Overridable (Visual Basic) är det en instansmedlem (det finns inget instansnyckelord). Det kommer att finnas lika många kopior av sådana medlemmar i minnet som det finns objekt som använder det. |
ordagrann | Fält | Värdet som tilldelas fältet är ett fast värde, känt vid kompileringstid, av en inbyggd värdetyp. Literalfält kallas ibland för konstanter. |
newslot eller åsidosättning | Alla | Definierar hur medlemmen interagerar med ärvda medlemmar som har samma signatur: newslot Döljer ärvda medlemmar som har samma signatur. åsidosätta Ersätter definitionen av en ärvd virtuell metod. Standardvärdet är newslot. |
static | Fält, metoder, egenskaper och händelser | Medlemmen tillhör den typ som den definieras på, inte till en viss instans av typen. medlemmen finns även om en instans av typen inte skapas och delas mellan alla instanser av typen. |
virtuell | Metoder, egenskaper och händelser | Metoden kan implementeras av en härledd typ och kan anropas statiskt eller dynamiskt. Om dynamiskt anrop används avgör typen av instans som gör anropet vid körning (i stället för den typ som är känd vid kompileringstiden) vilken implementering av metoden som anropas. Om du vill anropa en virtuell metod statiskt kan variabeln behöva omvandlas till en typ som använder den önskade versionen av metoden. |
Överbelastning
Varje typmedlem har en unik signatur. Metodsignaturer består av metodnamnet och en parameterlista (ordningen och typerna av metodens argument). Flera metoder med samma namn kan definieras inom en typ så länge deras signaturer skiljer sig åt. När två eller flera metoder med samma namn definieras, sägs metoden vara överbelastad. I är metoden till exempel System.CharIsDigit överbelastad. En metod tar en Char. Den andra metoden tar en String och en Int32.
Kommentar
Returtypen betraktas inte som en del av en metods signatur. Metoder kan alltså inte överbelastas om de endast skiljer sig efter returtyp.
Ärva, åsidosätta och dölja medlemmar
En härledd typ ärver alla medlemmar av dess bastyp. dessa medlemmar definieras på och är tillgängliga för den härledda typen. Beteendet eller egenskaperna hos ärvda medlemmar kan ändras på två sätt:
En härledd typ kan dölja en ärvd medlem genom att definiera en ny medlem med samma signatur. Detta kan göras för att göra en tidigare offentlig medlem privat eller för att definiera nytt beteende för en ärvd metod som är markerad som
sealed
.En härledd typ kan åsidosätta en ärvd virtuell metod. Den övergripande metoden ger en ny definition av metoden som ska anropas baserat på typen av värdet vid körning i stället för den typ av variabel som är känd vid kompileringstiden. En metod kan endast åsidosätta en virtuell metod om den virtuella metoden inte är markerad som
sealed
och den nya metoden är minst lika tillgänglig som den virtuella metoden.