Fırat Esmer

ANLATILAN SENİN HİKAYENDİR - KARL MARX

C# 7 - İlk Bakış

C# History

Visual Studio 2017'nin yayınlanması ile birlikte C# 7.0 da aramıza katılmış oldu. VS2017 RTM'e (son/kararlı hal) geçmeden önce dil hakkında bilgileri zaten ediniyor hatta kullanıyoruz. C# 7 ile gelen yeniliklerin yaşantımızda kullanacak kıvama gelmeden hemen önceki turumuza başlayalım.

Bahsedeceğim konular

  • Out Variables
  • Pattern Matching,
  • Tuples,
  • Local Functions,
  • Literals, Ref. Returns, Exceptions

Out Variables

  • Önceden tanımlamada var kullanılamıyor (int.TryParse(input, out var answer)),
  • Kullanmadan önce tanımlanması gerekiyor (demo),

Yukarıdaki sorunlara çözüm olarak Out Variables sunuldu.

// Eski yöntem
private static void Run()
{
	string name;
	string lastName;

	GetName(out name, out lastName);
	Console.WriteLine($"{name} {lastName}");
}

// C# 7.0 ile gelen yeni yöntem
private static void Run2()
{
	GetName(out string name, out string lastName);
	Console.WriteLine($"{name} {lastName}");
}

private static void GetName(out string name, out string lastName)
{
	name = "Fırat";
	lastName = "Esmer";
}

Pattern Matching

Pattern'in tanımı için şöyle güzel bir yorum var:

Syntactic elements that can test that a value has a certain "shape".

Bir değerin belirli bir şekle sahip olduğunu test edebilen sözdizimsel öğeler.

static void Main(string[] args)
{
	PrintSum(10);
	PrintSum2("10");
}

public static void PrintSum(object o)
{
	if (o is null) return; //Constant Pattern
	if (!(o is int i)) return; // Type Pattern (Int32)

	int sum = 0;

	for (int j = 0; j <= i; j++)
		sum += j;
}

public static void PrintSum2(object o)
{
	if (o is int i || o is string s && int.TryParse(s, out i))
	{
		int sum = 0;

		for (int j = 0; j <= i; j++)
			sum += j;
	}
}

Koşullu switch'e de bir göz atalım, burada gelen yenilik case durumunda koşul girebiliyor olmamız. Yani test edebiliyor olmamız.

class Program
{
	static void Main(string[] args)
	{
		Employee employee = new President();
		employee.Salary = 200000;
		employee.Years = 10;
		(employee as President).ManagedEmployeeNumber = 500;
		(employee as President).StockShares = 12000;

		// Switch içerisindeki sıralama önemli
		// Manager Employee'nin altında olsaydı hata alırdık
		// Kalıtım alan sınıf alınan sınıftan üstte olmalı
		switch (employee)
		{
			case President p when (p.StockShares < 10000):
				Console.WriteLine($"Düşük profilli yönetici hisse senedi payı : {p.StockShares}");
				break;

			case President p when (p.StockShares >= 10000):
				Console.WriteLine($"Yüksek profilli yönetici hisse senedi payı : {p.StockShares}");
				break;

			case Manager m:
				Console.WriteLine($"Yönetiye bağlı kişi : {m.ManagedEmployeeNumber}");
				break;

			case Employee e:
				Console.WriteLine($"Çalışan maaşı : {e.Salary}");
				break;
		}
	}
}

public class Employee
{
	public int Salary { get; set; }
	public int Years { get; set; }
}

public class Manager : Employee
{
	public int ManagedEmployeeNumber { get; set; }
}

public class President : Manager
{
	public int StockShares { get; set; }
}

Tuples

Metotlardan birden fazla değeri geri döndürmek istediğimizde aklımıza gelen en uygun yöntem out parametresi. Fakat out parametresinin de elimizi kolumuzu bağladığı bazı noktalar var. Mesela okunabilirliği zayıf, async metotlarla kullanılamıyor. Burada yardımımıza Tuple (System.Tuple<T>) yetişiyor. Tuple'ı başka bir Tuple'a convert edebilirsiniz. Tuple value type'dır (referans değil).

Öncelikle Tuples'ı kullanmak için NuGet Package kullanmamız gerektiğini belirteyim. Aşağıdaki resimde gördüğünüz gibi yüklemeyi gerçekleştirin.

System.Tuples Nuget Package

static void Main(string[] args)
{
	var numbers = GetThreeNumbers();
	// İsimlendirme işlemini biz yapmadığımız için
	// kendisi otomatik olarak yapıyor
	Console.WriteLine($"{numbers.Item1},{numbers.Item2},{numbers.Item3}");

	var numbersWithNames = GetThreeNumbersWithNames();
	Console.WriteLine($"{numbersWithNames.number1},{numbersWithNames.number2},{numbersWithNames.number3}");
}

public static (int, int, int) GetThreeNumbers()
{
	return (1, 56, 187);
}

public static (int number1, int number2, int number3) GetThreeNumbersWithNames()
{
	return (1, 56, 187);
}

Tuple ile Dictionary kullanımı

var tupleDictionary = new Dictionary<(int, int), string>();
tupleDictionary.Add((16, 21), "İki kardeşin yaşları");

// Sonuç = İki kardeşin yaşları
var result = tupleDictionary[(16, 21)];

Tuple Deconstruction örneği

static void Main(string[] args)
{
	(int number1, int number2, int number3) = GetThreeNumbers();
	Console.WriteLine($"{number1},{number2},{number3}");

	// Diğer kullanım şekli
	int _number1;
	int _number2;
	int _number3;
	(_number1, _number2, _number3) = GetThreeNumbers();
	Console.WriteLine($"{_number1},{_number2},{_number3}");
}

public static (int, int, int) GetThreeNumbers()
{
	return (1, 56, 187);
}

Local Functions

Local function, metot içerisinde metot kullanımıdır. Direkt örnekle açıklayayım, daha kolay olacaktır.

NOT : Örnekte Tuples kullanıldığı için Tuples başlığındaki gibi yükleme işlemini yapmanız gerekiyor.

static void Main(string[] args)
{
	// Fibonacci => 1, 1, 2, 3, 5, 8
	// Mevcut değerin bir önceki değer ile toplamı bir sonraki
	// değeri vermekte
	Console.WriteLine(Fibonacci(6));
	Console.Read();
	// Sonuç (6-1) + 8 = 13
}

public static int Fibonacci(int x)
{
	if (x < 0)
		throw new ArgumentException("Değer en az sıfır olmalı",
									nameof(x));

	return Fib(x).current;

	(int current, int previous) Fib(int i)
	{
		if (i == 0) return (1, 0);
		var (current, previous) = Fib(i - 1);
		return (current + previous, current);
	}
}

Literals, Ref. Returns, Exceptions

static void Main(string[] args)
{
	// Sonuç => 5781231
	Console.WriteLine(GetNumber());

	// Referans Return
	int[] numbers = { 1, 3, 5, 7, 9, 11 };
	ref int position = ref Substitute(5, numbers);
	position = -30;
	Console.WriteLine(numbers[2]);

	// Sonuç => Fırat
	Employee employee = new Employee("Fırat");
	Console.WriteLine(employee.Name);
	// Sonuç => Hata / Exception
	Employee employee2 = new Employee(null);
	Console.WriteLine(employee.Name);

	Console.Read();
}

// Literal: Altçizgi (underscore) seperator (ayırıcı)
// olarak değil dönüş tipi olarak dönüyor
private static int GetNumber()
{
	return 5_7_8_123_1;
}

// Reference Return örneği
private static ref int Substitute(int value, int[] numbers)
{
	for (int i = 0; i < numbers.Length; i++)
		if (numbers[i] == value)
			return ref numbers[i];

	throw new IndexOutOfRangeException("Bulunamadı!");
}

// Exception as expression örneği
public class Employee
{
	public string Name { get; }
	public Employee(string name) => Name = name ?? throw new ArgumentNullException();
}

Son olarak

C# 7 yenilikler listesini Microsoft Documents üzerinden incelemek için => https://docs.microsoft.com/en-us/dotnet/articles/csharp/whats-new/csharp-7

Yorum ekle

Loading