Implicit inskrivna lokala variabler (C#-programmeringsguide)
Lokala variabler kan deklareras utan att ange en explicit typ. Nyckelordet var
instruerar kompilatorn att härleda typen av variabel från uttrycket till höger om initieringsinitieringssatsen. Den härledda typen kan vara en inbyggd typ, en anonym typ, en användardefinierad typ eller en typ som definierats i .NET-klassbiblioteket. Mer information om hur du initierar matriser med var
finns i Implicit typade matriser.
I följande exempel visas olika sätt på vilka lokala variabler kan deklareras med var
:
// i is compiled as an int
var i = 5;
// s is compiled as a string
var s = "Hello";
// a is compiled as int[]
var a = new[] { 0, 1, 2 };
// expr is compiled as IEnumerable<Customer>
// or perhaps IQueryable<Customer>
var expr =
from c in customers
where c.City == "London"
select c;
// anon is compiled as an anonymous type
var anon = new { Name = "Terry", Age = 34 };
// list is compiled as List<int>
var list = new List<int>();
Det är viktigt att förstå att nyckelordet var
inte betyder "variant" och inte anger att variabeln är löst skriven eller senbunden. Det innebär bara att kompilatorn bestämmer och tilldelar den lämpligaste typen.
Nyckelordet var
kan användas i följande kontexter:
På lokala variabler (variabler som deklarerats i metodomfånget) som du ser i föregående exempel.
I en för initieringsinitieringssats.
for (var x = 1; x < 10; x++)
I en foreach-initieringsinitieringssats .
foreach (var item in list) {...}
I en using-instruktion .
using (var file = new StreamReader("C:\\myfile.txt")) {...}
Mer information finns i Använda implicit inskrivna lokala variabler och matriser i ett frågeuttryck.
var- och anonyma typer
I många fall är användningen av var
valfri och är bara en syntaktisk bekvämlighet. Men när en variabel initieras med en anonym typ måste du deklarera variabeln som var
om du behöver komma åt objektets egenskaper vid ett senare tillfälle. Det här är ett vanligt scenario i LINQ-frågeuttryck. Mer information finns i Anonyma typer.
Från källkodens perspektiv har en anonym typ inget namn. Om en frågevariabel har initierats med var
är det enda sättet att komma åt egenskaperna i den returnerade sekvensen av objekt att använda var
som typ av iterationsvariabel i -instruktionen foreach
.
class ImplicitlyTypedLocals2
{
static void Main()
{
string[] words = { "aPPLE", "BlUeBeRrY", "cHeRry" };
// If a query produces a sequence of anonymous types,
// then use var in the foreach statement to access the properties.
var upperLowerWords =
from w in words
select new { Upper = w.ToUpper(), Lower = w.ToLower() };
// Execute the query
foreach (var ul in upperLowerWords)
{
Console.WriteLine("Uppercase: {0}, Lowercase: {1}", ul.Upper, ul.Lower);
}
}
}
/* Outputs:
Uppercase: APPLE, Lowercase: apple
Uppercase: BLUEBERRY, Lowercase: blueberry
Uppercase: CHERRY, Lowercase: cherry
*/
Kommentarer
Följande begränsningar gäller för implicit skrivna variabeldeklarationer:
var
kan endast användas när en lokal variabel deklareras och initieras i samma instruktion. Variabeln kan inte initieras till null eller till en metodgrupp eller en anonym funktion.var
kan inte användas på fält i klassomfånget.Variabler som deklareras med hjälp
var
av kan inte användas i initieringsuttrycket. Det här uttrycket är med andra ord lagligt:int i = (i = 20);
men det här uttrycket skapar ett kompileringsfel:var i = (i = 20);
Flera implicit inskrivna variabler kan inte initieras i samma instruktion.
Om en typ med namnet
var
finns i omfånget matchas nyckelordetvar
till det typnamnet och behandlas inte som en del av en implicit skriven lokal variabeldeklaration.
Implicit inmatning med nyckelordet var
kan endast tillämpas på variabler i det lokala metodomfånget. Implicit skrivning är inte tillgängligt för klassfält eftersom C#-kompilatorn skulle stöta på en logisk paradox när koden bearbetades: kompilatorn måste känna till typen av fält, men den kan inte fastställa typen förrän tilldelningsuttrycket har analyserats och uttrycket kan inte utvärderas utan att känna till typen. Ta följande kod som exempel:
private var bookTitles;
bookTitles
är ett klassfält givet typen var
. Eftersom fältet inte har något uttryck att utvärdera är det omöjligt för kompilatorn att härleda vilken typ bookTitles
som ska vara. Dessutom är det inte heller tillräckligt att lägga till ett uttryck i fältet (som för en lokal variabel):
private var bookTitles = new List<string>();
När kompilatorn stöter på fält under kodkompilering registrerar den varje fälttyp innan de uttryck som är associerade med den bearbetas. Kompilatorn stöter på samma paradox som försöker parsa bookTitles
: den måste känna till typen av fält, men kompilatorn skulle normalt fastställa var
typen genom att analysera uttrycket, vilket inte är möjligt utan att känna till typen i förväg.
Du kanske upptäcker att det var
också kan vara användbart med frågeuttryck där den exakta konstruerade typen av frågevariabeln är svår att avgöra. Detta kan inträffa med grupperings- och beställningsåtgärder.
Nyckelordet var
kan också vara användbart när den specifika typen av variabel är omständlig att skriva på tangentbordet, eller är uppenbar eller inte lägger till kodens läsbarhet. Ett exempel där var
är användbart på det här sättet är med kapslade generiska typer som de som används med gruppåtgärder. I följande fråga är IEnumerable<IGrouping<string, Student>>
typen av frågevariabel . Så länge du och andra som måste behålla din kod förstår detta, är det inga problem med att använda implicita skrivningar för enkelhetens skull och korthet.
// Same as previous example except we use the entire last name as a key.
// Query variable is an IEnumerable<IGrouping<string, Student>>
var studentQuery3 =
from student in students
group student by student.Last;
Användningen av var
hjälper till att förenkla din kod, men dess användning bör begränsas till fall där den krävs, eller när den gör koden enklare att läsa. Mer information om när du ska använda var
korrekt finns i avsnittet Implicit inskrivna lokala variabler i artikeln C#-kodningsriktlinjer.