Giriş
Önceki yazımızda 1, fonksiyonel programlamanın temellerinden bahsederek, Func
ve
Action
delege türüne değindik ve bir fonksiyondan yeni bir fonksiyonun
nasıl döndürüleceğine dair kısa bir örnek yaptık.
Bu yazımızda, Func
ve Action
türlerini daha yakından tanımaya çalışacağız.
Action
Delege Türü
Action
delege türü, dönüş tipi olmayan (void
olan) fonksiyonları temsil etmek
için kullanılır.
Hiçbir parametre almayan ve hiçbir dönüş tipi olmayan fonksiyonlar için Action
delege türü kullanılır.
1public delegate void Action( );
Tek parametre alan fonksiyonlar içinse jenerik Action<T>
delegesi kullanılır.
1 public delegate void Action<in T>(T obj);
Action
delegesinin 16 jenerik parametreye kadar parametre alan türü mevcuttur.
1 public delegate void Action<in T1,in T2,in T3,in T4,in T5,in T6,in T7,in T8,
2 in T9,in T10, in T11,in T12,in T13,in T14,in T15,in T16>(
3 T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8,
4 T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13, T14 arg14, T15 arg15, T16 arg16);
Console.WriteLine
Fonksiyonlarını Action
ile Temsil Etmek
Console.WriteLine
fonksiyonunun (yanlış saymadıysam) 18 adet türevi (overload
)
mevcut. Dönüş tipleri void
olduğu için Action
ile temsil edilebilir.
Bunlardan birkaçı:
1 public static void WriteLine ();
2 public static void WriteLine (decimal value);
3 public static void WriteLine (string value);
4 public static void WriteLine (object value);
5 public static void WriteLine (string format, object arg0);
6 public static void WriteLine (char[] buffer, int index, int count);
WriteLine ()
metodu için bir delege atayalım ve fonksiyonu çağırmak için bu
delegeyi kullanalım. Hiçbir parametre almadığı için jenerik Action
delege
türünü kullanacağız.
1 Action newLine = Console.Writeline;
2 newLine();
Çıktısı konsolda boş bir satır.
WriteLine (decimal value)
için aynı işlemi yapalım. Bu defa, fonksiyonumuz tek
parametre alacağı için jenerik Action<T>
delege türevini kullanmamız gerekiyor.
1 Action<decimal> writeDecimal = Console.WriteLine;
2 writeDecimal(99.90m);
Çıktısı:
199.90
İki örnekte sağ tarafta Console.WriteLine
vermemize rağmen derleyici,
en uygun jenerik türü belirledi ve kapalı dönüştürme (Implicit Conversation)
işlemi uyguladı.
Aynı işlemleri diğer türevler için de uygulayalım:
1 Action<string> writeStr = Console.WriteLine;
2 writeStr("C# ile Fonskiyonel Programlamaya Giriş");
3
4 Action<object> writeObj = Console.WriteLine;
5 writeObj(new Dictionary<string, string>());
6 writeObj(null);
7
8 Action<string, object> writeObjFmt = Console.WriteLine;
9 writeObjFmt("{0:0.00}", 3.994m);
10
11 Action<char[], int, int> writeChrSubArray = Console.WriteLine;
12 char[] buffer = "Lorem ipsum di amet".ToArray();
13 writeChrSubArray(buffer, 6, 5);
Çıktısı:
1C# ile Fonskiyonel Programlamaya Giriş
2(0 items)
3null
43.99
5ipsum
Fonksiyonel Programlamadaki Yeri
Önceki yazımızda fonksiyonel programlamayı tanımlarken bahsettiğimiz:
- Fonksiyonların değişkenler gibi tanımlanabilmesi
- Fonksiyonların, diğer fonksiyonlara parametre olarak geçilebilmesi
yöntemlerini uygulayabilmek için Action
ve türevlerine ihtiyacımız olacak.
newLine
, writeDecimal
, writeObj
, writeObjFmt
, writeChrSubArray
artık birer
değişken oldukları için, bunları fonksiyonlarımızdan döndürebilir,
List
, Dictionary
gibi veri yapılarında saklayabiliriz.
Kullanıcı Tanımlı Action
Delegeler
Yukarıdaki örneklerde mevcut fonksiyonlara delege atadık. Bu defa ise
fonksiyonlarımızı Action
kullanarak tanımlayacağız.
1 Action writeHelloWorld = () => {
2 Console.WriteLine("Merhaba 🌍!");
3 };
Aşağıda yeni bir fonksiyon tanımlayarak bunları delegeler ile temsil edebilmek için C#‘ın bize sağladığı üç farklı yolu görüyorsunuz.
1 Action<string> writeWelcome1 = (user) => {
2 Console.WriteLine($"Hoşgeldiniz {user}.");
3 };
4
5 Action<string> writeWelcome2 = (string user) => {
6 Console.WriteLine($"Hoşgeldiniz {user}.");
7 };
8
9 Action<string> writeWelcome3 = new Action<string>( (user) => {
10 Console.WriteLine($"Hoşgeldiniz {user}.");
11 });
writeWelcome1
, writeWelcome2
ve writeWelcome3
, string
tipinde tek
parametre alan fonksiyonlarımız temsil ediyor.
writeHelloWorld
ise hiçbir parametre almayan fonksiyonumuzu temsil ediyor.
Tanımladığımız fonksiyonları delegeler aracılığıyla çağıralım:
1 writeHelloWorld();
2 writeWelcome1("Ahmed Şeref");
3 writeWelcome2("Ahmed Şeref");
4 writeWelcome3("Ahmed Şeref");
Çıktısı:
1Merhaba 🌍!
2Hoşgeldiniz Ahmed Şeref.
3Hoşgeldiniz Ahmed Şeref.
4Hoşgeldiniz Ahmed Şeref.
Action
Delegesini Listede Saklamak
Fonksiyonları listelerde saklayamıyoruz fakat delegeleri saklayabiliriz. Delegeleri sakladığımız listeleri kullanarak temsil ettikleri fonksiyonları çağırabiliriz.
1 var actions = new List<Action<string>>();
2 actions.Add(writeStr);
3 actions.Add(writeWelcome1);
4 actions.Add(writeWelcome2);
5 actions.Add(writeWelcome3);
6
7 actions.First() ("#1 | `Action`, listelerde saklanabilir");
8 actions.First() ("#2 | Listedeki delegeleri kullanarak, temsil ettiği");
9 actions.First() ("#3 | fonksiyonları bu şekilde çağırabilirsiniz");
Çıktısı:
1#1 | `Action`, listelerde saklanabilir
2#2 | Listedeki delegeleri kullanarak, temsil ettiği
3#3 | fonksiyonları bu şekilde çağırabilirsiniz
Tanımladığımız actions
listesi içindeki bütün delegeleri 🌍 parametresi
ile çağıralım.
1 foreach(Action<string> acc in actions) {
2 acc("🌍");
3 }
Çıktısı:
1🌍
2Hoşgeldiniz 🌍.
3Hoşgeldiniz 🌍.
4Hoşgeldiniz 🌍.
Sonuç
Bu yazımızda Action
delegesini tanımaya çalıştık ve fonksiyonel programlama
ile ilişkisini örneklerle açıklamaya çalıştık.
Bir sonraki yazımızda dönüş tipi void
olmayan fonksiyonlar için kullanmamız
gereken Func
delegesinden bahsetmeye çalışacağız.
Bağlantılar
- https://docs.microsoft.com/en-us/dotnet/api/system.action
- https://docs.microsoft.com/en-us/dotnet/api/system.action-16
- https://docs.microsoft.com/en-us/dotnet/api/system.console.writeline
- https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/language-specification/conversions#implicit-conversions