İlkay İlknur

just a developer...

Task.FromResult Metodu Ne İş Yapar, Nerede Kullanılır ?

Bu makaleye Github üzerinden katkıda bulunabilirsiniz.

Bugün C# ile kod yazarken en sık kullandığımız keywordlerden ikisi şüphesiz ki async & await keywordleri. Her ne kadar bu keywordleri bilinçli olarak kullanıyoruz muyuz konusunda tam emin olamasam da bazen async & await keywordunu kullanmaktan biraz daha ötesine geçmek gerekiyor.

Task objesi bildiğimiz üzere .NET içerisinde bir asenkron operasyonla ilgili tüm bilgileri içerisinde tutan sınıf. Yani bir asenkron operasyonun o anki durumu ne ? veya işlem gerçekleşirken bir exception oldu mu ? gibi sorularımız cevaplarını alacağımız sınıf bu sınıf. Dolayısıyla C# içerisindeki async ve await keywordleri de bu task tipini kullanarak arka planda uygun bir şekilde gereken yapıları oluşturuyorlar.

Task içerisindeki FromResult metodu da en basit anlamda yeni bir Task objesi yaratarak Task'ın durumunu tamamlanmış olarak işaretliyor ve parametre olarak verdiğiniz değeri de Task'ın sonucu olarak içerisine atıyor. Bu durumda aklınıza şu soru geliyor olabilir. Normalde async & await kullandığımızda Task yaratmamız gerekmiyor. Peki bu metot neden var ? Neden ortada bir asenkron operasyon yokken Task yaratmak durumunda kalıyoruz ? Hemen kısaca kullanım alanlarına bakalım...

Interface içerisindeki asenkron metot implementasyonları

Diyelim ki 3rd party bir kütüphane kullanıyorsunuz ve o kütüphaneyi kullanabilmeniz içinde belirli bir interface'i implemente eden bir tip yaratmanız gerekiyor.

interface IThirdLib
{
    Task<int> CountAsync();
}

Bu interface içerisindeki CountAsync metodunu implemente etmek istediğinizde bulunduğunuz platformda bu işlem asenkron yapılmıyor olabilir veya static bir değer döndürmeniz gerekebilir.

class MyClass : IThirdLib
{
    public Task<int> CountAsync()
    {
        return 0;
    }
}

veya

class MyClass : IThirdLib
{
    public Task<int> CountAsync()
    {
        return Directory.EnumerateDirectories(@"C:\").Count();
    }
}

Bu durumda async await keywordu kullanmadığımız için Task tipini arka planda compiler bizim için yaratmıyor ve dolayısıyla int'i ben Task tipine çeviremem diye hata veriyor. Aklınıza hemen Task.Run yaparım onu da await ederim geliyorsa hemen o fikri unutun ve sakın yapmayın. Task.Run'ı şuursuz olarak her Task gereken yerde kullanmamak gerektiğini sakın unutmayın.

Yukarıdaki gibi bir durumla karşılırsanız Task.FromResult metodunu kullanarak tamamlanmış bir Task objesi yaratıp onu metotdan dönebilirsiniz.

class MyClass : IThirdLib
{
    public Task<int> CountAsync()
    {
        return Task.FromResult(5);
    }
}

veya

class MyClass : IThirdLib
{
    public Task<int> CountAsync()
    {
        return Task.FromResult(Directory.EnumerateDirectories(@"C:\").Count());
    }
}

Böylece bizim implementasyonumuz senkron çalışacak ama aynı zamanda bizim yazdığımız tipi kullananlar da async await kullanarak metodumuzu çağırsalar bile herhangi bir sorun yaşamayacaklar.

Bazı durumlarda senkron bazı durumlarda asenkron çalışan metotlar

Yazdığımız metotlar duruma göre senkron veya asenkron çalışabilirler. Örneğin bazı durumlarda senkron olarak validasyon yapılıp bunun sonucuna göre asenkron operasyona başlamadan exception fırlatılabilir. Örneğin MSDN'deki şu örneğe bakarsak...

static Task<long> GetFileLengthsAsync(string filePath)
{
    if (!Directory.Exists(filePath))
    {
        return Task.FromException<long>(
                    new DirectoryNotFoundException("Invalid directory name."));
    }
    else
    {
        string[] files = Directory.GetFiles(filePath);
        if (files.Length == 0)
            return Task.FromResult(0L);
        else
            return Task.Run(() => {
                long total = 0;
                Parallel.ForEach(files, (fileName) => {
                    var fs = new FileStream(fileName, FileMode.Open,
                                            FileAccess.Read, FileShare.ReadWrite,
                                            256, true);
                    long length = fs.Length;
                    Interlocked.Add(ref total, length);
                    fs.Close();
                });
                return total;
            });
    }
}

Bir klasörüdeki tüm dosyaların toplam büyüklüğünü almak istediğimizde örneğin ilk if'e bakarsanız klasörün validasyonu yapılıyor ve eğer klasör yoksa metot doğrudan geri dönüyor. Else içerisindeki 1. if'e bakarsak da klasör içerisinde hiç dosya yoksa doğrudan 0 dönüyor. Sonrasında ise Task.Run ile asenkron operasyon başlatılıyor. Dolayısıyla bu metot aslında en içteki else ifadesine kadar senkron çalışıyor. Sonrasında ise asenkron olarak devam ediyor. İşte bu gibi durumlarda da Task.FromResult metodu kullanılabilir.

Task.FromResult'a benzer diğer metotlar

Task tipi içerisinde FromResult metoduna benzeyen başka metotlar da bulabilmeniz mümkün. Örneğin, FromException veya FromCancelled gibi metotlar. Bu metotlar da isimlerindeki durumlara uyan Task tiplerini yaratıp size verirler. İçerisindeki exception olan task tipi veya iptal edilen bir Task tipi gibi...

Task.CompletedTask

.NET Framework 4.6 ile beraber Task içerisine CompletedTask propertysi eklendi. Bu Task tipi de herhangi bir değer döndürmeyen tamamlanış bir Task objesi içerisinde barındırıyor. Yani yukarıdaki gibi durumlardan birinde metodun dönüş tipi Task<int> değil de Task olsaydı Task.CompletedTask kullanabiliriz.

Taskları Cacheleme

Task.FromResult metodu her çağırdığımızda yeni bir Task objesi bize geri veriyor. Dolayısıyla her Task.FromResult(0) dediğimizde hep sonuç olarak 0 değerini barındıran bir task bize geri dönüyor.

Bu gibi durumlarda sık sık bu metodun çağırılması aslında gereksiz bir şekilde object yaratılmasına ve memoryde gereksiz bir şekilde fazladan bu objelerin yer almasına neden oluyor. Bu gibi durumlarda sıkça başvurulan yöntemlerden biri bu Taskların cachelenmesi. Bunun için örnek olarak Roslyn içerisindeki Task cacheleme mekanizmasına bakmanızı tavsiye ederim.

Roslyn içerisindeki SpecializedTasks sınıfı source code'u : https://github.com/dotnet/roslyn/blob/master/src/Workspaces/Core/Portable/Utilities/SpecializedTasks.cs



C# 7.0 - Out Variables

Bu makaleye Github üzerinden katkıda bulunabilirsiniz.

C# 7.0 ile beraber gelecek olan ufak ama oldukça kullanışlı özelliklerden biri de out variable'lar. Aslında yazının devamını okuyunca bu özellik daha önce gelmedi mi diye de düşünebilirsiniz. Çünkü bu özelliğin ilk olarak C# 6.0 ile beraber gelmesi planlanıyordu ancak Visual Studip 2015 RC versiyonuna geldiğinde C# ekibi bu feature'ı release'e kadar yetiştiremeyeceğini düşündüğü için C# 6.0'dan çıkardı. Şimdi gelelim out variable'ların kullanımına.

out keyword'ü bizim bir metottan birden fazla değer döndürmemiz gerektiği durumlarda başvurduğumuz bir keyword. Örneğin, .NET Framework içerisindeki int.TryParse metoduna bakarsak bu metodun boolean bir değer döndürdüğünü görüyoruz. Aynı zamanda bir de out parametre alıyor ve buradan da parse ettiği değeri metodu çağıran yere geri veriyor. Bir örnek yaparsak,

int result;
string str = "123123";
bool isSucceeded = int.TryParse(str, out result);

</ out keyword'ünün kullanımının en sıkıntılı yanı out parametresi olarak vereceğimiz değişkeni metodu çağırmadan önce tanımlamış olmamız gerekliliği. Çünkü genelde kod yazarken bu tanımlamaları önceden yapmayı unutuyoruz ve out parametresini gördüğümüz anda bir üst satıra geçip o değişkeni tanımlamak zorunda kalıyoruz. Bu da bizi kod yazarken yavaşlatıyor. Artık C# 7.0 ile beraber bu dikkat dağınıklığı ve kod yazarken yavaşlama durumu sona eriyor ve out parametresi olan bir metodu çağırırken inline olarak out parametreyi tanımlayabiliyoruz.

string str = "123123";
bool isSucceeded = int.TryParse(str, out int result);

Bu şekilde gördüğünüz gibi result değişkenini out parametre geçerken tanımlıyoruz ve metot çağırımından sonra da bu değişkeni kullanabiliyoruz. Hatta isterseniz out parametre tanımlarken var keywordünü de kullanbilirsiniz.

string str = "123123";
bool isSucceeded = int.TryParse(str, out var result);

out Parametreden Kurtulma

out parametre kabul eden metotları kullanırken belki de sadece metodun dönüş değerini kullanacağımız ve out parametreyi aslında sadece mecbur kaldığımız için tanımladığımız durumlar olabilir. Mesela, int.TryParse metoduna verdiğiniz string'in bir int value'nun string karşılığı olup olmadığını merak ediyor olabilirsiniz. Dolayısıyla out parametresi olarak verdiğimiz değere hiçbir yerde ihtiyacınız olmayacaktır. Bu gibi durumlar için de yine C# 7.0 out variables syntaxını kullanarak out variable tanımlamaktan kurtulabiliriz. Bunun için out variable'ın adını yazmak yerine _ koyarsak out parametre tanımlamaktan kurtulmuş oluyoruz. Arka plandaki gerekli işlemleri derleyici kendisi hallediyor.

string str = "123123";
if (int.TryParse(str, out var _))
{

}

C# 7.0 içerisindeki belki de en ufak özelliklerden biri out variable'lar. Ancak çözdüğü probleme baktığımızda bu versiyonda en çok kullanılacak olan özelliklerden biri olmaya aday.

Bir sonraki yazıda görüşmek üzere...



C# 7.0 - Tuples

Bu makaleye Github üzerinden katkıda bulunabilirsiniz.

C# 7.0 ile beraber gelecek olan önemli özelliklerden biri de Tuple'lar. Tuple tiplerine aslında çokta yabancı değiliz. Tuple tipiyle ilk olarak .NET Framework 4.0 ile tanışmıştık. Hani şu içerisinde Item1, Item2, Item3 diye propertyler olan tipler 😃 Çoğu zaman aslında kullanmak istediğimiz ama bu property isimlerinden dolayı kullanma konusunda içimizin rahat olmadığı tipler 😃

Tupleların en önemli kullanım alanları aslında bir metottan birden fazla değer döndürmek zorunda kaldığımız durumlar. C# içerisinde aslında bir metottan birden fazla değer döndürmek istediğimizde out parametrelerini kullanabiliyoruz.

private void Foo(int param1, out int intReturnParam, out string stringReturnParam)
{

}

Ancak out parametreler maalesef async metotlarda kullanılamıyor. Dolayısıyla bu durumda Tuple tipini kullanmak durumunda kalabiliyoruz.

private async Task<Tuple<intstring>> FooAsync(int param1)
{

}

private async void Barrier()
{
    var result = await FooAsync(1);
    Debug.WriteLine($"{result.Item1} : {result.Item2}");
}

Bu durumda da metodu çağıran veya kullanan yazılımcılar aslında bu async metottan ne döndüğü konusunda hiçbir şekilde bilgi sahibi olamıyorlar. Item1, Item2 fieldlarını ne işe yaradığını, hangisinde hangi bilgi olduğunu iyi bir şekilde dökümante etmeniz gerekiyor. Ayrıca mevcut Tuple tipi bir class olduğu için heap allocationa neden oluyor.

Tüm bu nedenlerden dolayı aslında gerçek anlamda Tuple desteği C# 7.0 ile beraber geliyor. Peki C# 7.0'da Tuple'lar nasıl olacak. Gelelim bu kısma.

Not: İlk olarak bu özelliği kullanmadan önce projemize System.ValueTuple nuget paketini eklememiz gerekiyor.

Metotlarda birden fazla değer döndürmek istediğimizde döndüreceğimiz alanların tiplerini ve isimlerini parantez içerisinde yazmamız gerekecek.

static (int count, string value) Foo()
{

}

static Task<(int count, string value)> FooAsync()
{

}

Yukarıda gördüğünüz gibi Foo metodunun dönüş değeri bir tuple ve bu tuple'ın içerisinde count ve value diye 2 tane alan bulunuyor. Ayrıca Task döndüren asenkron metotların da dönüş tipleri gördüğünüz gibi tuple olabiliyor. Bu şekilde tuple dönüş tiplerini tanımladıktan sonra peki metot içerisinde bir tuple nasıl tanımlıyoruz kısmına bakalım.

static(int count, string value) Foo()
{
    var retVal = (count: 1, value: "Foo");
    return retVal;
}

Parantez içerisinde sadece alanın adını ve değerini yazdığınızda da compiler arka planda aynı anonymous objectlerde olduğu gibi alanın tipini kendisi buluyor ve ona uygun tuple tipini yaratıyor. Ayrıca yine tipin compiler tarafından bilindiği durumlarda da tuple'lardaki field adlarının pekte önemi olmuyor. Compiler arka planda ilgili çevrimi kendisi yapıyor. Önemli olan tuple tipindeki alanların tiplerinin uyuşması.

static (int count, string value) Foo()
{
    var retVal = (c: 1, v: "Foo");
    return retVal;
}

Tuple Deconstruction

Bir metottan veya herhangi bir yerden bir tuple döndüğünde o tuple içerisindeki değerleri ayrıştırmak ve metodun devamında ayrıştırılmış halini kullanmak önemli. Bu yüzden tuple içerisindeki alanları ayrıştırıp içerisindeki değerleri değişkenlere atamak için de kolay bir syntax geliyor C# 7.0 ile.

static void Main(string[] args)
{
    var (count, value) = Foo();
}

static (int count, string value) Foo()
{
    var retVal = (c: 1, v: "Foo");
    return retVal;
}

Main metodunda göründüğü gibi Foo metodundan dönen tuple tipi içerisindeki alanları count ve value ismindeki local değişkenlere atamasını yapabiliyoruz. Böylece aslında tuple tipleri tamamen görünmez bir şekilde kalabiliyorlar. Yani siz bir metottan tuple döndüğünü biliyorsanız, bu tuple içerisindeki alanları hemen hızlıca lokal değişkenlere alıp kodunuzu temiz tutabilirsiniz.

Bazen de metotlardan dönen tuple içerisindeki sadece belirli alanlar işinize yarayabilir. Bu durumda tuple içerisindeki tüm alanları deconstruct etmek yerine istediğiniz değerleri deconstruct edip değişkenlere atayabilirsiniz. Bunun için yukarıda gösterdiğim syntax'ı kullanarak değişken ismi yerine _ koymanız yeterli.

static void Main(string[] args)
{
    var (count, _) = Foo();
}

static (int count, string value) Foo()
{
    var retVal = (c: 1, v: "Foo");
    return retVal;
}

C# 7.0 ile beraber gelen tuple'ların Framework içerisinde bulanan Tuple'lardan bazı farkları var. Bunlardan ilki C# 7.0 tuple'larının struct olması. Böylece bu tupleların yaratılmaları daha az maliyetli. Ayrıca C# 7.0 tuple'ları mutable. Yani bir tuple yarattıktan sonra fieldın değerini değiştirebilirsiniz. Ancak .NET Framework içerisindeki Tuple tipleri immutable. Yani yarattıktan sonra fieldın değerini sadece okuyabilirsiniz, değiştiremezsiniz.

Bir sonraki yazıda görüşmek üzere...



C# 7.0 - Pattern Matching

Şu ana kadar C# 7.0 ile beraber gelmesi planlanan pek çok özelliği inceledik. Bu blog postu da saymazsak incelemediğimiz sadece 3 özellik kalıyor. BU özellikler pattern matching, out var ve tuples.

Bu blog postta ise pattern matching özelliğine bakacağız. C# 7.0 ile beraber gelecek en büyük özelliklerden biri olan pattern matching ile ilgili çektiğim videoyu aşağıdan izleyebilirsiniz.

Video Linki : https://www.youtube.com/watch?v=HzSh0PFBfoQ

Pattern Matching Kod Örnekleri: https://github.com/ilkayilknur/csharp-7-new-features/tree/master/PatternMatching

Görüşmek Üzere



C# 7.0 Kod Örnekleri

C# 6.0 zamanlarında özellikleri anlatan kod örneklerini Github üzerinden paylaşmıştım. C# 7.0 versiyonu da artık yavaş yavaş belirginleşmeye ve release olmaya doğru giderken benzer tarzda örnekleri C# 7.0 içinde koymaya karar verdim.

İlgili örneklere https://github.com/ilkayilknur/csharp-7-new-features adresinden ulaşabilirsiniz. Hatta ekleyebileceğiniz özel kullanım durumları da varsa pull request gönderebilirsiniz.

Görüşmek Üzere



C# 7.0 - Digit Separators

Bu makaleye Github üzerinden katkıda bulunabilirsiniz.

Not : Bu makaledeki örnekleri denemek için gereken ortam kurulum bilgisini buradan alabilirsiniz.

C# 7.0 ile beraber gelmesi planlanan ufak özelliklerden biri de digit separatorler. Digit separatorler ile numeric değer tanımlamaları sırasında istediğiniz bölümde basamakları ayırabiliyorsunuz. Böylece kod yazarken tanımlamış olduğunuz numeric değişkenlerin taşıdıkları değerler daha okunabilir olurken hem de siz tanımlama esnasında basamakları ayırabildiğiniz için hata yapma olasılığınız daha düşük oluyor. Digit separator olarak ise _ kullanıyoruz.

Örneğin,

int x = 1_000_000;
double y = 1_00.0_9;

Digit separatorlerin bir diğer kullanım alanı da binary literal'lar. Binary literal tanımlamaları esnasında da digit separatorleri kullanmamız mümkün.

Örneğin,

int x = 0b11_00_0_01;
double y = 0b1_00;

Bu ufak özellikle ilgili yazımızda bu kadar. Bir sonraki C# 7.0 özelliğinde görüşmek üzere...



C# 7.0 - Binary Literals

Bu makaleye Github üzerinden katkıda bulunabilirsiniz.

Not : Bu makaledeki örnekleri denemek için gereken ortam kurulum bilgisini buradan alabilirsiniz.

C# 7.0 ile beraber gelmesi muhtemel özelliklerden biride Binary Literals özelliği. Aslında C# design meetinglerini takip edenler için bu özellik süpriz bir özellik değil. Çünkü aslında aynı özellik C# 6.0'da da planlanıyordu ancak release döneminde bu özellik ne yazık ki C# 6.0'a dahil edilmedi.

İşin magazin tarafını bir kenara bırakırsak :) binary literals ile kod içerisinde binary olarak tanımlamalar yapabiliyorsunuz. Bunu yapmak için binary ifadenin başına 0b veya 0B yazmanız yeterli.

Örneğin,

static void Main(string[] args)
{
    int x = 0b1100001;
    double y = 0b100;
}

Gördüğünüz gibi kullanımı oldukça basit. Gelelim bu özellik nerelerde işimize yarayacak kısmına. Enumlara Flags attribute'ünü ekleyip 2'nin üssü bir biçimde değerler verdiğimizde enumlar üzerinde bitwise operasyonlar yapabiliyoruz. (Enumlar üzerinde bitwise operasyonlar ile ilgili yazmış olduğum yazıyı inceleyebilirsiniz. http://www.ilkayilknur.com/coklu-enum-degerleriyle-calismak) Burada 2'nin üssü değerleri verirken binary literalleri kullanabiliriz. Böylece hızlı bir şekilde ve daha az hata olasılığıyla hızlı bir şekilde kodumuzu yazabiliriz.

[Flags]
enum Colors
{
    Red = 0b1,
    Green = 0b10,
    Blue = 0b100
}

Gördüğünüz gibi binary literallerin bana göre en önemli kullanım alanı burası olacak. Bunun yanında C# ekibi binary ifadeleri öğrenen developerların da C# içerisinde eğitim amaçlı binary literalleri kullanacaklarını düşünüyorlar.

C# 7.0 binary literals özelliğiyle ilgili yazımız bu kadar. Zaten gördüğünüz gibi oldukça ufak bir özellik :) Bir sonraki yazıda görüşmek üzere...



C# 7.0 - Local Functions

Bu makaleye Github üzerinden katkıda bulunabilirsiniz.

Not : Bu makaledeki örnekleri denemek için gereken ortam kurulum bilgisini buradan alabilirsiniz.

C# 7.0 ile beraber gelmesi muhtemel en basit özelliklerden biride local functions özelliği. Hemen örnek yapmadan önce ilk olarak bu özelliğe ne gerek vardı sorusunun cevabını vermeye çalışalım.

Kod yazarken metotların çok fazla uzadığı ve bakımının zorlaştığı senaryolarda metot içerisindeki fonksiyonel bölümleri ayrı bir metot yaparız ve ilgili metot içerisinden de dışarıya aldığımız diğer metodu çağırırız. Bu ufak helper metotlarımız aslında baktığımızda sadece tek bir metot tarafından kullanılırlar ancak tanımlandıkları class'ın bir üyesi olurlar. Dolayısıyla bu helper metotları private olarak tanımlasak bile herhangi bir developer class içerisindeki başka bir metot içerisinden de istemememize rağmen bu metodu çağırabilir.

class Foo
{
    void Bar()
    {
        List<int> list = new List<int>();
        //Do something
        HelperMethod();
    }

    private void HelperMethod()
    {

    }
}

Örneğin yukarıdaki kodda HelperMethod isimli metot aynı class içerisindeki başka bir metottan da çağırılabilir.

class Foo
{
    void Bar()
    {
        List<int> list = new List<int>();
        //Do something
        HelperMethod();
    }

    private void HelperMethod()
    {

    }

    void Bar2()
    {
        HelperMethod();
    }
}

Bu aslında istenmeyen birşey olsa da bunun önüne geçmek pek mümkün değil. Tek kaçış yolu lambda ifadesi kullanarak Func veya Action tipinde bu helper metotları tanımlamak.

class Foo
{
    void Bar()
    {
        List<int> list = new List<int>();
        Action helper = () => { };
        //Do something
        helper();
    }
}

Bu durumda helper kısmı lambda ifadasi ile tanımladığımız için bu lambda ifadesi sadece Bar metodu içerisinden çağırılabilir ve erişilebilir. Böylece aslında en baştan amaçladığımız şeyi gerçekleştirmiş oluruz. Ancak Action ve Func olarak tanımlamanın bazı kısıtlamaları ile performans ve memory bakımından da bazı dezavantajları var.

Sahip oldukları kısıtlamalardan bazıları

  • Lambda ifadeleri generic olarak tanımlanamaz.
  • Lambda ifadeleri içerisinde ref, params ve out olarak parametre tanımlayamayız.
  • Lambda ifadelerini recursive olarak çağırmak için ufak bir trick yapmak gerekiyor. Tanımlama esnasında kendisini çağıramaz.

Tüm bu sıkıntılardan ötürü C# 7.0'da local functions özelliğinin getirilmesi planlanıyor. Şimdi gelelim local functions özelliğinin kullanımına.

class Foo
{
    void Bar()
    {
        List<int> list = new List<int>();
        void HelperMethod()
        {

        }

        HelperMethod();
    }
}

Yukarıda da gördüğünüz gibi metot içerisinde yeni bir metot tanımlamaktan başka birşey yapmıyoruz aslında. Dolayısıyla out, ref ve params parametrelerini de kullanabiliyoruz. Ayrıca bu metotların çağırımında da herhangi bir ekstra performans kaybı veya ekstra memory kullanımı da olmuyor. Local functionlar sadece tanımlı bulundukları metot içerisinden erişilebilir durumdalar. Yani başka bir metot içerisinden local function'ın çağırılması gibi bir durum söz konusu da değil. Yukarıdaki kodda da gördüğünüz gibi bir local functionı çağırmadan önce yukarıda o local function'ı tanımlamış olmak gerekiyor. Ayrıca local functionda, içerisinde bulunduğu metot içerisindeki her elemana da ulaşabilirsiniz.

class Foo
{
    void Bar()
    {
        List<int> list = new List<int>();
        void HelperMethod()
        {
            foreach (var item in list)
            {

            }
        }

        HelperMethod();
    }
}

C# 6.0 ve C# 7.0 Birarada

Yazıyı sonlandırmadan önce C# 6.0'da gelen expression-bodied function members özelliğini kullanarak local functions tanımlamadan bahsetmek istiyorum. Böylece tek satırlık bir local functionınız olduğunda hızlı bir şekilde bu özelliği kullanarak local functions tanımlayabilirsiniz.

class Foo
{
    void Bar()
    {
        List<int> list = new List<int>();
        void HelperMethod() => Console.WriteLine("Hello");

        HelperMethod();
    }
}

Evet, local functionsla ilgili bu yazıda bahsedeceklerimiz bu kadar. Gördüğünüz gibi ufak ama faydalı bir özellik gibi duruyor. Tabi C# developerların bu özelliği ne kadar benimseyeceklerini de merak etmiyor değilim.

Bir sonraki yazıda görüşmek üzere...



C# 7.0 Özelliklerini Nasıl Test Ederiz ?

Bu makaleye Github üzerinden katkıda bulunabilirsiniz.

Bir önceki blog yazısında C# 7.0 yeniliklerinden bahsettiğim videomu paylaşmıştım. Diyelim ki videoyu izlediniz veya başka yerlerden okuyup heyecanlandınız ve C# 7.0 özelliklerini test etmek istiyorsunuz :) Bu özellikleri test edebilmeniz için önünüzde 2 yol var. Biri kısmen kolay olan yol diğeri ise oldukça zorlu :) Önce kolay olandan başlayalım.

Visual Studio 15 Preview Üzerinde Test Etmek

Şu anda C# 7.0 özelliklerini test etmenin en kolay yolu Visual Studio 15 Preview kullanmak. Visual Studio 15 Preview sürümü adı üzerinde henüz preview olduğu için production makinanıza kurmanızı kesinlikle tavsiye etmiyorum. Bu yüzden bilgisayarınızda bir sanal makina yaratıp orada Visual Studio 15'i kurup testlerinizi yapabilirsiniz. Bir diğer alternatif ise Azure üzerinde Visual Studio 15 Preview imajlı bir VM yaratmak.

Visual Studio 15 Preview Installer Linki : http://aka.ms/vsnext

Visual Studio 15 Preview'ı kurdunuz ve hemen bir proje yaratıp özellikleri test etmek istiyorsunuz. Bir örnek yaptınız ama o da ne projeniz derlenmiyor ve hata veriyor.

Bu hatayı almamızın sebebi C# 7.0 özelliklerinin her birinin feature flagleri arkasına alınması. Yani ekip hızlı bir şekilde istediği özellikleri açıp kapatabiliyor gerekli olduğunda. Bu hatayı aşmanın yolu ise oldukça basit. Test yaptığımız projeye conditional compilation symbols olarak __DEMO__ ve __DEMO_EXPERIMENTAL__ 'ı eklemek.

Bu işlemi de yaptıktan sonra kodunuz başarılı olarak derlenecektir. Ancak her Visual Studio 15 Preview versiyonunda, duyurulan C# 7.0 özellikleri olmayabilir. Örneğin bu yazının yazıldığı dönemde bulunan Visual Studio 15 Preview içerisinde Tuple özellikleri henüz bulunmuyor.

Roslyn Source Code'unu Çalıştırıp Test Etmek

Gelelim diğer opsiyona. Github üzerinden Roslyn projesinin kodlarını indirip projeyi derleyip aynı şekilde özellikleri test edebilirsiniz. Daha önce bunu denemiş biri olarak uyarmam gerekir ki bu iş göründüğü kadar kolay değil. Kısaca yol göstermem gerekirse

Şimdiden bu opsiyonla uğraşacaklara kolaylıklar diliyorum :) Daha öncede bahsettiğim gibi en kolay opsiyon Visual Studio 15 Preview üzerinden testleri yapmak.

Bir sonraki yazıda görüşmek üzere.



C# 7.0'da Bizi Neler Bekliyor ?

Bu makaleye Github üzerinden katkıda bulunabilirsiniz.

C# 7.0'da Bizi Neler Bekliyor ?

C# 7.0 ile ilgili planlamalar daha C# 6.0 release olmadan önce başlasada bazı şeyler tam oturmadan herhangi bir paylaşımda bulunmak istememiştim. Artık Build konferansıyla beraber yavaş yavaş ana temaların belirginleşmesinden sonra C# 7.0 yazılarına başlamadan önce durumu özetleyen ve özelliklere kısaca değindiğim bir video çektim. Eğer C# 7.0 ile beraber neler gelecek diye merak ediyorsanız aşağıdaki videoyu izleyip bilgi sahibi olabilirsiniz.



Video Linki : https://www.youtube.com/watch?v=JPPWPtwXMFA