Aracılığıyla paylaş


C# 6 Yeni Özelliklere Genel Bakış

C# dilinin sürüm 6'sı, daha az ortak kod, geliştirilmiş netlik ve daha fazla tutarlılık sağlamak için dili geliştirmeye devam eder. Daha temiz başlatma söz dizimi, catch/finally bloklarında await özelliğini ve null koşullu ? işleci özellikle yararlıdır.

Not

C# dilinin en son sürümü (sürüm 7) hakkında bilgi için C# 7.0'daki Yenilikler makalesine bakın

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

C# 6 videosundaki yenilikler

C# 6 kullanma

C# 6 derleyicisi, Mac için Visual Studio'nin tüm son sürümlerinde kullanılır. Komut satırı derleyicileri kullananlar, 4.0 veya üzerini döndürdüğünü mcs --version onaylamalıdır. Mac için Visual Studio kullanıcılar mono 4 (veya daha yeni) yüklü olup olmadığını denetlemek için Ayrıntıları Gösterme Mac için Visual Studio > Mac için Visual Studio > hakkında.

Daha Az Ortak

statik kullanma

Numaralandırmalar ve gibi bazı sınıflar öncelikli olarak System.Mathstatik değerlerin ve işlevlerin sahipleridir. C# 6'da, bir türün tüm statik üyelerini tek using static bir deyimle içeri aktarabilirsiniz. C# 5 ve C# 6'daki 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 staticve Math.Egibi Math.PI ortak const alanları doğrudan erişilebilir yapmaz:

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öntemleri ile statik kullanma

Tesis using static , genişletme yöntemleriyle biraz farklı çalışır. Uzantı yöntemleri kullanılarak staticyazılmasına rağmen, üzerinde çalışılması gereken bir örnek olmadan anlamlı değildir. using static Bu nedenle, uzantı yöntemlerini tanımlayan bir türle kullanıldığında, uzantı yöntemleri hedef türlerinde (yöntemin this türü) kullanılabilir hale gelir. Örneğin, using static System.Linq.Enumerable tüm LINQ türlerini getirmeden nesne API'sini IEnumerable<T> 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: uzantı yöntemi Enumerable.Where diziyle ilişkilendirilirken, statik yöntem String.Join türüne String başvurmadan çağrılabilir.

nameof İfadeleri

Bazen, bir değişken veya alan verdiğiniz ada başvurmak isteyebilirsiniz. C# 6'da nameof(someVariableOrFieldOrType) dizesini "someVariableOrFieldOrType"döndürür. Örneğin, bir ArgumentException oluştururken hangi bağımsız değişkenin geçersiz olduğunu adlandırmak isteyebilirsiniz:

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

İfadelerin nameof en büyük avantajı, tür denetlenmeleri ve araç destekli yeniden düzenleme ile uyumlu olmalarıdır. İfadelerin nameof tür denetimi, türleri dinamik olarak ilişkilendirmek için kullanılan durumlarda string özellikle hoş karşılanır. Örneğin, iOS'ta bir string içindeki nesnelerin prototipini UITableViewCell oluşturmak için kullanılan türü belirtmek için a UITableViewkullanılır. nameof bu ilişkilendirmenin yazım hatası veya dikkatsiz yeniden düzenleme nedeniyle başarısız olmadığından emin olabilir:

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

öğesine bir nitelenmiş ad nameofgeçirebilirsiniz ancak yalnızca son öğe (son .öğeden sonra) döndürülür. Örneğin, Xamarin.Forms'da veri bağlaması 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));

öğesine yapılan iki çağrı SetBinding aynı değerleri geçiriyor: nameof(ReactiveType.StringField) başlangıçta "StringField"bekleyebileceğiniz gibi değil "ReactiveType.StringField" .

Null koşullu İşleç

C# için yapılan önceki güncelleştirmelerde, null değer atanabilir değerleri işlerken ortak kod miktarını azaltmak için null atanabilir türler ve null birleşim işleci ?? kavramları tanıtılmıştır. C# 6 bu temaya "null-koşullu işleç" ?.ile devam eder. İfadenin sağ tarafındaki bir nesnede kullanıldığında, null koşullu işleç nesne değilse null ve null değilse üye değerini döndürür:

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]

(Hem hem de length0length1 türünden int?çıkarılır)

Önceki örnekteki son satır null koşullu işlecini null birleşim işleciyle birlikte ?? gösterir?. Yeni C# 6 null koşullu işleci, dizideki 2. öğeyi döndürür null ; bu noktada null birleşim işleci devreye girip diziye lengths bir 0 sağlar (bunun uygun olup olmadığı elbette soruna özgüdür).

Null koşullu işleç, birçok uygulamada gerekli olan ortak null denetimi miktarını büyük ölçüde azaltmalıdır.

Belirsizliklerden dolayı null koşullu işleçte bazı sınırlamalar vardır. Bir temsilciyle yapmak isteyebileceğiniz gibi, parantez içinde 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 yine de bir -checking ortak bloğu üzerinde belirgin bir nulliyileştirmedir:

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

Dize İlişkilendirme

String.Format İşlev geleneksel olarak dizinleri biçim dizesinde yer tutucu olarak kullanmıştır; örneğin, String.Format("Expected: {0} Received: {1}.", expected, received). Elbette, yeni bir değer eklemek her zaman bağımsız değişkenleri saymak, yer tutucuları yeniden numaralandırmak ve yeni bağımsız değişkeni bağımsız değişken listesinde doğru sırada eklemek için can sıkıcı küçük bir görevi içerir.

C# 6'nın yeni dize ilişkilendirme özelliği üzerinde String.Formatbüyük ölçüde iyileştirir. Artık, ön eki olan $bir dizedeki değişkenleri doğrudan adlandırabilirsiniz. Örneğin:

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

Değişkenler elbette işaretlidir ve yanlış yazılmış veya kullanılamayan bir değişken derleyici hatasına neden olur.

Yer tutucuların basit değişkenler olması gerekmez, herhangi bir ifade olabilir. Bu yer tutucuların içinde, bu tırnak işaretlerinden kaçmadan tırnak işaretlerini kullanabilirsiniz. Örneğin, aşağıdakilere "s" dikkat edin:

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

Dize ilişkilendirme, hizalama ve biçimlendirme söz dizimini String.Formatdestekler. Daha önce yazdığınız {index, alignment:format}gibi, 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şkilendirmesi için String.Formatsöz dizimsel şekerdir: dize değişmez değerleriyle @"" kullanılamaz ve yer tutucu kullanılmasa bile ile constuyumlu değildir:

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

Dize ilişkilendirmesi ile işlev bağımsız değişkenleri oluşturmanın yaygın kullanım örneğinde, yine de kaçış, kodlama ve kültür sorunları konusunda dikkatli olmanız gerekir. SQL ve URL sorguları elbette temizleme açısından kritik öneme sahiptir. gibi String.Formatdize ilişkilendirmesi de kullanır CultureInfo.CurrentCulture. Kullanmak CultureInfo.InvariantCulture biraz daha fazla sözcükle ifade edilir:

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 çeşitli kısa yollar sağlar.

Otomatik Özellik Başlatma

Otomatik özellikler artık alanlarla aynı kısa sürede başlatılabilir. Sabit otomatik özellikler yalnızca bir alıcıyla 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 şekilde başlatılması hem genel bir alan tasarrufu özelliğidir hem de nesnelerinde değişmezliği vurgulama isteğinde bulunan geliştiriciler için bir boondur.

Dizin Başlatıcıları

C# 6, dizin başlatıcısı olan türlerde hem anahtarı hem de değeri ayarlamanıza olanak tanıyan dizin başlatıcılarını tanıtır. Bu genellikle -style veri yapıları içindir Dictionary:

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 Gövdeli İşlev Üyeleri

Lambda işlevlerinin birkaç avantajı vardır ve bunlardan biri yalnızca alan tasarrufu sağlar. Benzer şekilde, ifade gövdeli sınıf üyeleri küçük işlevlerin C# 6'nın önceki sürümlerinde mümkün olandan biraz daha kısa ifade edilmesine olanak tanır.

İfade gövdeli işlev üyeleri, geleneksel blok söz dizimi yerine lambda ok söz dizimini kullanır:

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

Lambda-ok söz diziminin açık returnbir kullanmadığını fark edin. döndüren voidişlevler için ifadenin de bir deyimi olması gerekir:

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

İfade gövdeli üyeler hala yöntemler için desteklenen kurala async tabidir, ancak özelliklere tabi 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şlemeyi doğru yapmak zordur. C# 6'daki yeni özellikler, özel durum işlemeyi daha esnek ve tutarlı hale getirir.

Özel Durum Filtreleri

Tanım gereği, özel durumlar olağan dışı durumlarda ortaya çıkar ve belirli bir tür özel durumunun oluşabileceği tüm yöntemler hakkında mantık yürütmesi ve kodlanması çok zor olabilir. C# 6, çalışma zamanı tarafından değerlendirilen bir filtreyle yürütme işleyicisini koruma özelliğini tanıtır. Bu, normal catch(ExceptionType) bildirimden sonra bir when (bool) desen eklenerek yapılır. Aşağıdaki filtre, parametreyle ilgili ayrıştırma hatasını date diğer ayrıştırma hatalarından farklı olarak ayırt eder.

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

yakalamada bekle... Sonunda...

async C# 5'te sunulan özellikler, dil için bir oyun değiştirici olmuştur. C# 5'te ve awaitfinally bloklarında catch izin verilmedi, bu özellik değeri async/await göz önüne alındığında bir sıkıntı. C# 6 bu sınırlamayı kaldırarak aşağıdaki kod parçacığında gösterildiği gibi program aracılığıyla zaman uyumsuz sonuçların tutarlı bir şekilde beklenmesine olanak tanı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ştiricileri daha üretken hale getirmek için gelişmeye devam ederken, iyi uygulamaları ve destekleyici araçları da tanıtıyor. Bu belgede C# 6'daki yeni dil özelliklerine genel bir bakış verilmiş ve bunların nasıl kullanıldığı kısaca gösterilmiştir.