C# 6 yeni özelliklerine genel bakış

C# dilinin 6. sürümü, daha az ortak kod, geliştirilmiş açıklık ve daha fazla tutarlılık sağlamak için dili geliştirmeye devam etmektedir. Temizleyici başlatma sözdizimi, catch/finally bloklarından await kullanma özelliği ve null koşullu? işleç özellikle faydalıdır.

Not

C# dilinin en son sürümü (sürüm 7) hakkında daha fazla bilgi için c# 7,0 'deki yenilikler makalesine bakın

Bu belge C# 6 ' nın yeni özelliklerini tanıtır. Mono derleyicisi tarafından tam olarak desteklenir ve geliştiriciler tüm Xamarin hedef platformları genelinde yeni özellikleri kullanmaya başlayabilir.

C# 6 video 'daki yenilikler

C# 6 kullanma

C# 6 derleyicisi, tüm Mac için Visual Studio son sürümlerinde kullanılır. Komut satırı derleyicilerini kullanan bu kişiler, mcs --version 4,0 veya üzeri bir değer döndürdüğünü doğrulamamalıdır. Mac için Visual Studio kullanıcılar, Mac için Visual Studio hakkında bilgi Mac için Visual Studio, > ayrıntıları göster' e başvurarak Mono 4 ' ün (veya daha yeni) yüklenip yüklenmediğini denetleyebilir.

Daha az ortak

statik kullanma

Numaralandırmalar ve gibi belirli sınıflar System.Math , birincil olarak statik değerlerin ve işlevlerin sahiplerini de vardır. C# 6 ' da, bir türün tüm statik üyelerini tek bir ifadeyle içeri aktarabilirsiniz using static . C# 5 ve C# 6 ' da tipik bir trigonometrik işlevi karşılaştırın:

// Classic C#
class MyClass
{
    public static Tuple<double,double> SolarAngleOld(double latitude, double declination, double hourAngle)
    {
        var tmp = Math.Sin (latitude) * Math.Sin (declination) + Math.Cos (latitude) * Math.Cos (declination) * Math.Cos (hourAngle);
        return Tuple.Create (Math.Asin (tmp), Math.Acos (tmp));
    }
}

// C# 6
using static System.Math;

class MyClass
{
    public static Tuple<double, double> SolarAngleNew(double latitude, double declination, double hourAngle)
    {
        var tmp = Asin (latitude) * Sin (declination) + Cos (latitude) * Cos (declination) * Cos (hourAngle);
        return Tuple.Create (Asin (tmp), Acos (tmp));
    }
}

using static , ve gibi genel const alanları Math.PI doğrudan erişilebilir hale getirir Math.E :

for (var angle = 0.0; angle <= Math.PI * 2.0; angle += Math.PI / 8) ... 
//PI is const, not static, so requires Math.PI

Uzantı yöntemleriyle statik kullanma

using staticTesis, genişletme yöntemleriyle biraz farklı şekilde çalışır. Uzantı yöntemleri kullanılarak yazılmış olsa da static , üzerinde çalışılacak bir örnek olmadan mantıklı değildir. Bu nedenle using static , uzantı yöntemlerini tanımlayan bir türle birlikte kullanıldığında, uzantı yöntemleri hedef türünde (yöntemin türü) kullanılabilir hale gelir this . Örneğin, using static System.Linq.EnumerableIEnumerable<T> Tüm LINQ türlerini GETIRMEDEN nesnelerin API 'sini genişletmek için kullanılabilir:

using static System.Linq.Enumerable;
using static System.String;

class Program
{
    static void Main()
    {
        var values = new int[] { 1, 2, 3, 4 };
        var evenValues = values.Where (i => i % 2 == 0);
        System.Console.WriteLine (Join(",", evenValues));
    }
}

Önceki örnekte, davranış farkı gösterilmektedir: genişletme yöntemi, Enumerable.Where dizi ile ilişkilendirilir, ancak statik yöntem String.Join türe başvuru olmadan çağrılabilir String .

NameOf Ifadeleri

Bazen, bir değişken veya alan vermiş olduğunuz ada başvurmak istersiniz. C# 6 ' da, nameof(someVariableOrFieldOrType) dizeyi döndürür "someVariableOrFieldOrType" . Örneğin, bir örneğini oluştururken ArgumentException hangi bağımsız değişkeni geçersiz bir şekilde adlandırmak isteyebilirsiniz:

throw new ArgumentException ("Problem with " + nameof(myInvalidArgument))

İfadelerin baş avantajı, nameof tür denetimli ve araç ile desteklenen yeniden düzenleme ile uyumlu olmalardır. İfadelerin tür denetimi özellikle, nameofstring türleri dinamik olarak ilişkilendirmek için kullanılan durumlarda hoş geldiniz. Örneğin, a iOS a içindeki string nesneleri prototip için kullanılan türü belirtmek için kullanılır UITableViewCellUITableView . nameof Hatalı bir veya özensiz yeniden düzenlemesi nedeniyle bu ilişkinin başarısız olmasına güvence altına alabilir:

public override UITableViewCell GetCell (UITableView tableView, NSIndexPath indexPath)
{
    var cell = tableView.DequeueReusableCell (nameof(CellTypeA), indexPath);
    cell.TextLabel.Text = objects [indexPath.Row].ToString ();
    return cell;
}

Tam adı öğesine geçirebilseniz de nameof , yalnızca son öğe (son ' dan sonra . ) döndürülür. Örneğin, Xamarin. Forms 'a veri bağlama ekleyebilirsiniz:

var myReactiveInstance = new ReactiveType ();
var myLabelOld.BindingContext = myReactiveInstance;
var myLabelNew.BindingContext = myReactiveInstance;
var myLabelOld.SetBinding (Label.TextProperty, "StringField");
var myLabelNew.SetBinding (Label.TextProperty, nameof(ReactiveType.StringField));

İçin iki çağrı SetBinding aynı değerleri nameof(ReactiveType.StringField) geçirmektir "StringField" , ancak "ReactiveType.StringField" Başlangıçta bekleyeceğiniz gibi değildir.

Null-koşullu Işleç

C# ' den önceki güncelleştirmelerde, null yapılabilir ?? değerler işlenirken ortak kod miktarını azaltmak için null yapılabilir türler ve null birleşim işleci kavramları tanıtılmıştır. C# 6, bu temaya "null-Conditional işleci" ile devam eder ?. . Bir ifadenin sağ tarafındaki bir nesne üzerinde kullanıldığında, null koşullu işleç, nesne yoksa null ve aksi takdirde üye değerini döndürür null :

var ss = new string[] { "Foo", null };
var length0 = ss [0]?.Length; // 3
var length1 = ss [1]?.Length; // null
var lengths = ss.Select (s => s?.Length ?? 0); //[3, 0]

( length0 Ve öğelerinin length1 türü olarak algılanır int? )

Önceki örnekte yer alan son satır, null- ? koşullu işleci null ?? birleşim işleciyle birlikte gösterir. Yeni C# 6 null-koşullu işleci null dizideki 2. öğede döner ve bu noktada, null birleşim işlecinin üzerine gelin ve lengths diziye (uygun olup olmadığına bakılmaksızın, soruna özel) 0 sağlar.

Null şartlı operatör, çok sayıda uygulamada gereken ortak null denetim miktarını gecenin döndürmelidir.

Belirsizlikleri nedeniyle null şartlı operatör üzerinde bazı sınırlamalar vardır. Bir ? temsilciyle yapmak isteyebileceğiniz için, parantez içine alınmış bağımsız değişken listesiyle hemen takip edemezsiniz:

SomeDelegate?("Some Argument") // Not allowed

Ancak, Invoke bağımsız değişken listesinden ayırmak için kullanılabilir ? ve bir ortak denetim bloğu üzerinde hala işaretlenmiş bir geliştirme olur null :

public event EventHandler HandoffOccurred;
public override bool ContinueUserActivity (UIApplication application, NSUserActivity userActivity, UIApplicationRestorationHandler completionHandler)
{
    HandoffOccurred?.Invoke (this, userActivity.UserInfo);
    return true;
}

Dize Ilişkilendirme

String.Formatİşlev, geleneksel olarak dizinleri biçim dizesinde yer tutucu olarak kullandı, örn.. String.Format("Expected: {0} Received: {1}.", expected, received Kuşkusuz, yeni bir değer eklemek her zaman bağımsız değişkenlerin sayımını yapmak, yer tutucuları yeniden numaralandırma ve yeni bağımsız değişkeni bağımsız değişken listesinde doğru sırayla eklemektir.

C# 6 ' nın yeni dize ilişkilendirme özelliği, üzerine büyük ölçüde gelişir String.Format . Şimdi, bir dize önekli bir dizede doğrudan değişkenleri yazabilirsiniz $ . Örneğin:

$"Expected: {expected} Received: {received}."

Değişkenler, yapılır, işaretlendi ve yanlış yazılmış veya kullanılabilir olmayan bir değişken, bir derleyici hatasına neden olur.

Yer tutucuların basit değişkenler olması gerekmez, herhangi bir ifade olabilir. Bu yer tutucularda, tırnak işaretleri bu teklifleri kaçış olmadan kullanılabilir. Örneğin, aşağıdaki gibi konusuna göz önünde edin "s" :

var s = $"Timestamp: {DateTime.Now.ToString ("s", System.Globalization.CultureInfo.InvariantCulture )}"

Dize ilişkilendirme, öğesinin hizalama ve biçimlendirme sözdizimini destekler String.Format . Daha önce yazdığınız gibi {index, alignment:format} C# 6 ' da şunu yazarsınız {placeholder, alignment:format} :

using static System.Linq.Enumerable;
using System;

class Program
{
    static void Main ()
    {
        var values = new int[] { 1, 2, 3, 4, 12, 123456 };
        foreach (var s in values.Select (i => $"The value is { i,10:N2}.")) {
            Console.WriteLine (s);
        }
    Console.WriteLine ($"Minimum is { values.Min(i => i):N2}.");
    }
}

Sonuç:

The value is       1.00.
The value is       2.00.
The value is       3.00.
The value is       4.00.
The value is      12.00.
The value is 123,456.00.
Minimum is 1.00.

Dize ilişkilendirme için sözdizimsel cukr String.Format : @"" dize sabit değerleri ile kullanılamaz ve ile uyumlu değildir const , ancak hiçbir yer tutucu kullanılmasa bile ile uyumlu değildir:

const string s = $"Foo"; //Error : const requires value

Dize ilişkilendirme ile işlev bağımsız değişkenleri oluşturmanın yaygın kullanım durumunda, kaçış, kodlama ve kültür sorunları konusunda dikkatli olmanız gerekir. SQL ve URL sorguları, elbette temizleme için kritik öneme sahiptir. İle olduğu gibi String.Format , dize ilişkilendirme öğesini kullanır CultureInfo.CurrentCulture . Kullanmak CultureInfo.InvariantCulture biraz daha az bir sözcük:

Thread.CurrentThread.CurrentCulture  = new CultureInfo ("de");
Console.WriteLine ($"Today is: {DateTime.Now}"); //"21.05.2015 13:52:51"
Console.WriteLine ($"Today is: {DateTime.Now.ToString(CultureInfo.InvariantCulture)}"); //"05/21/2015 13:52:51"

Başlatma

C# 6, özellikleri, alanları ve üyeleri belirtmek için bir dizi kısa yol sağlar.

Otomatik özellik başlatma

Otomatik özellikler artık alanlarla aynı kısa şekilde başlatılabilir. Sabit otomatik özellikler yalnızca bir alıcı ile yazılabilir:

class ToDo
{
    public DateTime Due { get; set; } = DateTime.Now.AddDays(1);
    public DateTime Created { get; } = DateTime.Now;

Oluşturucuda, yalnızca alıcı otomatik özelliğinin değerini ayarlayabilirsiniz:

class ToDo
{
    public DateTime Due { get; set; } = DateTime.Now.AddDays(1);
    public DateTime Created { get; } = DateTime.Now;
    public string Description { get; }

    public ToDo (string description)
    {
        this.Description = description; //Can assign (only in constructor!)
    }

Otomatik özelliklerin bu başlatması hem genel bir alan kaydetme özelliği hem de geliştiricilerin nesnelerinde dengesizliği vurgulamak için bir Boon vardır.

Dizin başlatıcıları

C# 6 Dizin başlatıcıları tanıtır, bu, hem anahtar hem de değeri bir Dizin Oluşturucu içeren türlerde ayarlamanıza olanak sağlar. Genellikle, bu stil için Dictionary veri yapılarıdır:

partial void ActivateHandoffClicked (WatchKit.WKInterfaceButton sender)
{
    var userInfo = new NSMutableDictionary {
        ["Created"] = NSDate.Now,
        ["Due"] = NSDate.Now.AddSeconds(60 * 60 * 24),
        ["Task"] = Description
    };
    UpdateUserActivity ("com.xamarin.ToDo.edit", userInfo, null);
    statusLabel.SetText ("Check phone");
}

İfade-Bodied Işlev üyeleri

Lambda işlevlerinin çeşitli avantajları vardır, bunlardan biri yalnızca alan tasarrufu sağlar. Benzer şekilde, ifade Bodied sınıf üyeleri, küçük işlevlere C# 6 ' nın önceki sürümlerinde mümkün olandan çok daha succinctly bir şekilde ifade versin.

İfade-Bodied işlev üyeleri geleneksel blok sözdizimi yerine lambda ok söz dizimini kullanır:

public override string ToString () => $"{FirstName} {LastName}";

Lambda ok sözdiziminin açık bir şekilde kullanmıyorsa emin olun return . Döndüren işlevler için void , ifadesinin de bir deyim olması gerekir:

public void Log(string message) => System.Console.WriteLine($"{DateTime.Now.ToString ("s", System.Globalization.CultureInfo.InvariantCulture )}: {message}");

İfade-Bodied Üyeler hala yöntemler için desteklenen kurala tabidir, async ancak özellikler için değildir:

//A method, so async is valid
public async Task DelayInSeconds(int seconds) => await Task.Delay(seconds * 1000);
//The following property will not compile
public async Task<int> LeisureHours => await Task.FromResult<char> (DateTime.Now.DayOfWeek.ToString().First()) == 'S' ? 16 : 5;

Özel durumlar

Bunun iki yolu yoktur: özel durum işleme doğru bir şekilde sürer. C# 6 ' daki yeni özellikler özel durum işleme daha esnek ve tutarlı hale getirir.

Özel durum filtreleri

Tanım gereği olağan dışı koşullarda özel durumlar oluşur ve belirli bir türde özel durum ortaya çıkabilecek Tüm yollarla ilgili olarak neden ve kodu bir istisna olabilir. C# 6, bir yürütme işleyicisini çalışma zamanında değerlendirilen bir filtreyle koruma yeteneği sunar. Bu when (bool) , normal bildirimden sonra bir model eklenerek yapılır catch(ExceptionType) . Aşağıdaki şekilde, bir filtre date diğer ayrıştırma hatalarının aksine parametresiyle ilgili ayrıştırma hatasını ayırır.

public void ExceptionFilters(string aFloat, string date, string anInt)
{
    try
    {
        var f = Double.Parse(aFloat);
        var d = DateTime.Parse(date);
        var n = Int32.Parse(anInt);
    } catch (FormatException e) when (e.Message.IndexOf("DateTime") > -1) {
        Console.WriteLine ($"Problem parsing \"{nameof(date)}\" argument");
    } catch (FormatException x) {
        Console.WriteLine ("Problem parsing some other argument");
    }
}

Catch içinde await... son olarak...

asyncC# 5 ' te tanıtılan yetenekler, dil için bir oyun değiştiricisine sahiptir. C# 5 ' te awaitcatch ve bloklarına izin verilmediğine finally , özelliğin değeri verilen bir annoyance async/await . C# 6, aşağıdaki kod parçacığında gösterildiği gibi zaman uyumsuz sonuçların program aracılığıyla sürekli olarak beklenmesine izin vererek bu kısıtlamayı ortadan kaldırır:

async void SomeMethod()
{
    try {
        //...etc...
    } catch (Exception x) {
        var diagnosticData = await GenerateDiagnosticsAsync (x);
        Logger.log (diagnosticData);
    } finally {
        await someObject.FinalizeAsync ();
    }
}

Özet

C# dili, geliştiricilerin daha üretken olmasını sağlamak için gelişirken iyi uygulamalar ve destekleyici araçlar da sağlar. Bu belgede C# 6'daki yeni dil özelliklerine genel bir bakış ve bunların nasıl kullanıldıklarını kısaca gösterebilirsiniz.