Kan jag använda C# 3 i mina .NET 2.0 projekt?
Förord
De flesta torde väl redan ha märkt att Visual Studio 2008 nyligen har släppts och med den kom version 3 av C# som för med sej lite godbitar i form av syntax. Nu är ju vissa av olika anledningar tvungna att fortsättningsvis hålla sej till .NET Framework 2.0 (som kom med Visual Studio 2005), och har kanske därför inte kollat speciellt mycket på vad dom nya möjligheterna i Visual Studio 2008 innebär. Vissa av nyheterna går att använda även i .NET 2.0 projekt, vi ska här se på dessa.
Inledning
En av nyheterna i Visual Studio 2008 är så kallad multi targeting, vilket innebär att vi kan välja vilken version av ramverket vi vill utveckla för. Dom stödda versionerna är 2.0, 3.0 samt 3.5.Nu funderar du kanske ifall du utvecklar för version 2.0 av ramverket, kan du då använda dej av ny funktionalitet i C# 3?
Svaret som du kanske redan gissat är ja eftersom de flesta nyheterna enbart är ”syntactic sugar” som kompilatorn ”skriver om” innan det blir till MSIL kod.
Jag har i den här artikeln tänkt att kort gå igenom vilka nyheter som kan användas även med version 2.0 av ramverket.
Implicit typade lokala variabler
(Eng: implicitly typed local variables and arrays)Med C# 3 kommer möjligheten att använda sej av implicit typade lokala variabler med hjälp av nyckelordet var.
Var innebär inte typlöshet eller dynamisk typning, utan att kompilatorn tar reda på vilken typ det handlar om i och med att du tilldelar variabeln ett värde, och för att det inte ska bli ett kaos av det hela så tillåts detta enbart för lokala variabler.
var answer = 42; // variableln answer är av typen int
var dict = new Dictionary>();
var fel = null; // ogiltigt, eftersom typen inte kan avgöras
var fel2; // ogiltigt, eftersom typen inte kan avgöras
Enkla egenskaper
(Eng: simple properties)Hur många gånger har du skrivit något I stil med följande och tyckt att det känns onödigt drygt? Det vill säga egenskaper utan någon extra logik.
class Whatever {
private string m_foo;
public string Foo {
get { return m_foo; }
set { m_foo = value; }
}
}
C# 3 tillåter dej att skriva enkla egenskaper på följande sätt, (och kompilatorn skapar automatiskt bakomliggande fält)
public string Foo { get; set; }
Objekt och kollektionsinitialiserare
(Eng: Object and collection initializers)I vissa fall kan det vara praktiskt att direkt kunna ge värden åt egenskaper även om klassen i fråga inte har en konstruktor som tar lämpliga parametrar. Detta tillåter objektinitialiserare.
Exempelvis om vi har följande “data”klass som beskriver en cd skiva.
class Cd {
public int Id { get; set; }
public string Artist {get; set; }
public string Name { get; set; }
public Cd() {
}
public Cd(int id) {
Id = id;
}
}
Vi kan nu skapa nya instanser av denna t.ex. på följande vis:
Cd cd = new Cd {Id=42, Artist=”Muse”, Name=”Absolution” };
Cd cd2 = new Cd (1) { Artist=”U2” };
Vi kan även initialisera exempelvis en lista på liknande sätt:
List arkiv = new List{
new Cd {Name = ”U2” },
new Cd {Name = “U3” }
};
Anonyma typer
(Eng: anonymous types)Anonyma typer används kanske främst i samband med LINQ, men går även att användas annars vid behov.
var anon = new { Name=”John Doe”, Age = 42 };
Här skapas alltså en ny typ med kompilatorgenererat namn med två egenskaper: Name av typen string och Age av typen int. Eftersom anonyma typer måste använda sej av nyckelordet var, så kan dessa användas enbart för lokala variabler.
Lambda uttryck
Lambda uttryck är kanske den mest obekanta nyheten, men som kanske kan beskrivas som en fortsättning på anonyma metoder som introducerades i C# 2.
// hitta alla skivor av U2
// vi kan explicit ange parametertyp
List u2skivor = arkiv.FindAll((Cd c) => c.Name == "U2");
// vi kan låta parametertypen bestämmas implicit
List u2skivor = arkiv.FindAll((c) => c.Name == "U2");
// vi kan lämna bort parenteserna ifall lambda uttrycket enbart tar en parameter
List u2skivor = arkiv.FindAll(c => c.Name == "U2");
Extensionsmetoder
(Eng: extension methods)Har du någonsin känt att det saknas en speciell metod på en klass som du inte har möjlighet att förändra? Låt säga att du alltid velat att string klassen haft en InvertCase metod som gör versaler till gemener och vice versa.
Med extensionsmetoder kan du ”sätta till” metoder utifrån, bakom kulisserna gör kompilatorn ett anrop till en statisk metod, men du får trevligare syntax.
public static class MinaExtensionsMetoder {
public static string InvertCase(this string input) {
return /*implementation här */;
}
}
// användning
string whatever = “FooBarBaz”;
string ny = whatever.InvertCase();
På grund av att kompilatorn “korvar om” koden till ett statiskt metodanrop funkar det även att exempelvis utöka object klassen med en IsNull metod.
public static bool IsNull(this object obj) {
return obj == null;
}
// …
Cd ingen = null;
If (ingen.IsNull()) {
Console.WriteLine(”villkoret sant”); // vi kommer hit
}
Allt jag har skrivit om ovan går att använda genast, men försöker du kopiera extensionsmetoderna kommer du att få ett kompilatorfel ”Cannot define a new extension method because the compiler required type 'System.Runtime.CompilerServices.ExtensionAttribute' cannot be found. Are you missing a reference to System.Core.dll?”
Eftersom System.Core hör till .NET 3.5 ramverket så verkar det ju som extensionsmetoder inte går att använda?
Faktum är att ifall man gör en egen implementation av ExtensionAttribute enligt nedanstående så fungerar det. Kanske inte jättesnyggt, men den smällen får man ta om man vill använda extensionsmetoder med .NET 2 ramverket.
// hack to be able to use extension methods without .NET 3.5
namespace System.Runtime.CompilerServices
{
public class ExtensionAttribute : Attribute
{
public ExtensionAttribute()
{
}
}
}
Sammanfattning
I den här artikeln har jag visat att man kan använda sej C# 3 syntax även om man kodar mot .NET 2.0 ramverket. Hoppas den här artikeln väckte din nyfikenhet att testa på. Kommentarer, frågor samt konstruktiv feedback mottages gärna!
Ps. Ursäkta eventuella översättningsgrodor. Jag använder vanligtvis engelska programmeringstermer.
0 Kommentarer