C # 'da temsilci kullanımınız nedir?
C # 'da temsilci kullanımınız nedir?
Yanıtlar:
Artık C # 'da lambda ifadeleri ve anonim yöntemlere sahip olduğumuza göre, delegeleri çok daha fazla kullanıyorum. Mantığı uygulamak için her zaman ayrı bir yönteme sahip olmanız gereken C # 1'de, bir temsilci kullanmak çoğu zaman bir anlam ifade etmiyordu. Bugünlerde delegeleri şunlar için kullanıyorum:
Delegeler birçok amaç için çok kullanışlıdır.
Böyle bir amaç, bunları veri dizilerini filtrelemek için kullanmaktır. Bu durumda, bir bağımsız değişkeni kabul eden ve temsilcinin uygulamasına bağlı olarak doğru veya yanlış döndüren bir yüklem delege kullanırsınız.
İşte aptalca bir örnek - Bundan daha yararlı bir şey çıkarabileceğinize eminim:
using System;
using System.Linq;
using System.Collections.Generic;
class Program
{
static void Main()
{
List<String> names = new List<String>
{
"Nicole Hare",
"Michael Hare",
"Joe Hare",
"Sammy Hare",
"George Washington",
};
// Here I am passing "inMyFamily" to the "Where" extension method
// on my List<String>. The C# compiler automatically creates
// a delegate instance for me.
IEnumerable<String> myFamily = names.Where(inMyFamily);
foreach (String name in myFamily)
Console.WriteLine(name);
}
static Boolean inMyFamily(String name)
{
return name.EndsWith("Hare");
}
}
static Boolean inMyFamily(String name)
Yöntem temsilci olduğu. Bir temsilciyi parametre olarak nerede alır. Temsilciler, yöntem adını .Where(delegate)
temsilci haline getirdiğinizde yalnızca işlev işaretçileri olduğundan . İnMyFamily bir boole türü döndürdüğünden, aslında bir yüklem olarak kabul edilir. Dayanaklar yalnızca booleleri döndüren temsilcilerdir.
Başka ilginç bir cevap buldum:
Bir iş arkadaşım az önce bana şu soruyu sordu - .NET'teki temsilcilerin amacı nedir? Cevabım çok kısaydı ve internette bulamadığı bir şeydi: bir yöntemin uygulanmasını geciktirmek.
Kaynak: LosTechies
Tıpkı LINQ'nun yaptığı gibi.
Fonksiyon tipli değişkenleri ve parametreleri bildirmek için temsilciler kullanabilirsiniz.
Misal
"Kaynak ödünç alma" modelini düşünün. Müşteri kodunun aradaki kaynağı "ödünç almasına" izin verirken, bir kaynağın oluşturulmasını ve temizlenmesini kontrol etmek istersiniz.
Bu, bir temsilci türü bildirir.
public delegate void DataReaderUser( System.Data.IDataReader dataReader );
Bu imzayla eşleşen herhangi bir yöntem, bu türden bir temsilciyi başlatmak için kullanılabilir. C # 2.0'da, bu örtük olarak, yalnızca yöntemin adını kullanarak veya anonim yöntemler kullanarak yapılabilir.
Bu yöntem, türü bir parametre olarak kullanır. Temsilcinin çağrısını not edin.
public class DataProvider
{
protected string _connectionString;
public DataProvider( string psConnectionString )
{
_connectionString = psConnectionString;
}
public void UseReader( string psSELECT, DataReaderUser readerUser )
{
using ( SqlConnection connection = new SqlConnection( _connectionString ) )
try
{
SqlCommand command = new SqlCommand( psSELECT, connection );
connection.Open();
SqlDataReader reader = command.ExecuteReader();
while ( reader.Read() )
readerUser( reader ); // the delegate is invoked
}
catch ( System.Exception ex )
{
// handle exception
throw ex;
}
}
}
İşlev, aşağıdaki gibi anonim bir yöntemle çağrılabilir. Anonim yöntemin kendi dışında bildirilen değişkenleri kullanabileceğini unutmayın . Bu son derece kullanışlıdır (örnek biraz yapmacık olsa da).
string sTableName = "test";
string sQuery = "SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME='" + sTableName + "'";
DataProvider.UseReader( sQuery,
delegate( System.Data.IDataReader reader )
{
Console.WriteLine( sTableName + "." + reader[0] );
} );
Temsilciler genellikle bir yöntemle bir arayüz yerine kullanılabilir, bunun yaygın bir örneği gözlemci modeli olabilir. Diğer dillerde, bir şeyin olduğuna dair bir bildirim almak istiyorsanız, aşağıdaki gibi bir şey tanımlayabilirsiniz:
class IObserver{ void Notify(...); }
C # 'da bu daha yaygın olarak, işleyicinin bir temsilci olduğu olaylar kullanılarak ifade edilir, örneğin:
myObject.SomeEvent += delegate{ Console.WriteLine("..."); };
Örneğin, bir listeden bir öğe kümesi seçerken, bir koşulu bir işleve geçirmeniz gerektiğinde, temsilcilerin kullanılabileceği başka bir harika yer:
myList.Where(i => i > 10);
Yukarıdakiler, aşağıdaki gibi de yazılabilen lambda sözdiziminin bir örneğidir:
myList.Where(delegate(int i){ return i > 10; });
Temsilcileri kullanmanın yararlı olabileceği başka bir yer de fabrika işlevlerini kaydetmektir, örneğin:
myFactory.RegisterFactory(Widgets.Foo, () => new FooWidget());
var widget = myFactory.BuildWidget(Widgets.Foo);
Umarım bu yardımcı olur!
Bu konuya gerçekten geç geliyorum ama bugün delegelerin amacını anlamakta güçlük çekiyordum ve amaçlarını iyi açıkladığını düşündüğüm aynı çıktıyı veren iki basit program yazdım.
NoDelegates.cs
using System;
public class Test {
public const int MAX_VALUE = 255;
public const int MIN_VALUE = 10;
public static void checkInt(int a) {
Console.Write("checkInt result of {0}: ", a);
if (a < MAX_VALUE && a > MIN_VALUE)
Console.WriteLine("max and min value is valid");
else
Console.WriteLine("max and min value is not valid");
}
public static void checkMax(int a) {
Console.Write("checkMax result of {0}: ", a);
if (a < MAX_VALUE)
Console.WriteLine("max value is valid");
else
Console.WriteLine("max value is not valid");
}
public static void checkMin(int a) {
Console.Write("checkMin result of {0}: ", a);
if (a > MIN_VALUE)
Console.WriteLine("min value is valid");
else
Console.WriteLine("min value is not valid");
Console.WriteLine("");
}
}
public class Driver {
public static void Main(string [] args) {
Test.checkInt(1);
Test.checkMax(1);
Test.checkMin(1);
Test.checkInt(10);
Test.checkMax(10);
Test.checkMin(10);
Test.checkInt(20);
Test.checkMax(20);
Test.checkMin(20);
Test.checkInt(30);
Test.checkMax(30);
Test.checkMin(30);
Test.checkInt(254);
Test.checkMax(254);
Test.checkMin(254);
Test.checkInt(255);
Test.checkMax(255);
Test.checkMin(255);
Test.checkInt(256);
Test.checkMax(256);
Test.checkMin(256);
}
}
Delegates.cs
using System;
public delegate void Valid(int a);
public class Test {
public const int MAX_VALUE = 255;
public const int MIN_VALUE = 10;
public static void checkInt(int a) {
Console.Write("checkInt result of {0}: ", a);
if (a < MAX_VALUE && a > MIN_VALUE)
Console.WriteLine("max and min value is valid");
else
Console.WriteLine("max and min value is not valid");
}
public static void checkMax(int a) {
Console.Write("checkMax result of {0}: ", a);
if (a < MAX_VALUE)
Console.WriteLine("max value is valid");
else
Console.WriteLine("max value is not valid");
}
public static void checkMin(int a) {
Console.Write("checkMin result of {0}: ", a);
if (a > MIN_VALUE)
Console.WriteLine("min value is valid");
else
Console.WriteLine("min value is not valid");
Console.WriteLine("");
}
}
public class Driver {
public static void Main(string [] args) {
Valid v1 = new Valid(Test.checkInt);
v1 += new Valid(Test.checkMax);
v1 += new Valid(Test.checkMin);
v1(1);
v1(10);
v1(20);
v1(30);
v1(254);
v1(255);
v1(256);
}
}
Biraz farklı bir kullanım, yansımayı hızlandırmaktır; Yani, her seferinde yansıma kullanmak yerine, Delegate.CreateDelegate
bir yöntem (a MethodInfo
) için (yazılan) bir delege oluşturmak ve bunun yerine bu delegeyi çağırmak için kullanabilirsiniz. Bu daha sonra çok denetler zaten yapılmış olarak, daha hızlı arama başına.
İle Expression
, anında kod oluşturmak için de aynısını yapabilirsiniz - örneğin, Expression
çalışma zamanında seçilen bir tür için + operatörünü temsil eden bir + operatörünü kolayca oluşturabilirsiniz (dilin sağlamadığı jenerikler için operatör desteği sağlamak için) ; ve Expression
yazılı bir temsilciye bir derleyebilirsiniz - iş bitti.
Temsilciler, olayları her kullandığınızda kullanılır - çalıştıkları mekanizma budur.
Ek olarak, temsilciler LINQ sorgularını kullanmak gibi şeyler için çok kullanışlıdır. Örneğin, birçok LINQ sorgusu Func<T,TResult>
, filtreleme için kullanılabilen (genellikle ) bir temsilci alır .
Bir örnek burada görüldüğü gibi olabilir . Belirli gereksinimleri karşılayan bir nesneyi işlemek için bir yönteminiz var. Ancak, nesneyi birden çok şekilde işleyebilmek istiyorsunuz. Ayrı yöntemler oluşturmak zorunda kalmak yerine, nesneyi bir temsilciye işleyen ve temsilciyi nesneleri seçen yönteme ileten bir eşleştirme yöntemi atayabilirsiniz. Bu şekilde, tek seçici yönteme farklı yöntemler atayabilirsiniz. Bunu kolayca anlaşılır kılmaya çalıştım.
İş parçacıklarıyla iletişim kurmak için temsilciler kullanıyorum.
Örneğin, bir dosya indiren bir kazanma formları uygulamam olabilir. Uygulama, indirme işlemini yapmak için bir çalışan iş parçacığı başlatır (bu, GUI'nin kilitlenmesini önler). Çalışan iş parçacığı, GUI'nin durum çubuğunu güncelleyebilmesi için durum mesajlarını (örn. İndirme ilerlemesi) ana programa geri göndermek için temsilciler kullanır.
Olay işleyici için
Yöntemi bir yöntem parametrelerinde geçirmek için
Etkinlikler, diğer anynch işlemleri
Davranışı özetlemek istediğiniz her an, ancak onu tek tip bir şekilde çağırın. Olay İşleyicileri, geri arama işlevleri, vb. Arabirimler ve yayınlar kullanarak benzer şeyler gerçekleştirebilirsiniz, ancak bazen davranışın bir türe veya nesneye bağlı olması gerekmez . Bazen özetlemeniz gereken bir davranışınız olur.
Tembel parametre başlatma! Önceki tüm yanıtların yanı sıra (strateji modeli, gözlemci kalıbı, vb.), Delegeler, parametrelerin tembel olarak başlatılmasını sağlar. Örneğin, oldukça fazla zaman alan ve belirli bir DownloadedObject döndüren bir Download () işleviniz olduğunu varsayalım. Bu nesne, belirli Koşullara bağlı olarak bir Depo tarafından tüketilir. Genellikle şunları yaparsınız:
storage.Store(conditions, Download(item))
Ancak, temsilcilerle (daha doğrusu lambdalar), mağazanın imzasını değiştirerek aşağıdakileri yapabilirsiniz, böylece bir Koşul ve bir Func <Item, DownloadedObject> alır ve bunu şu şekilde kullanabilirsiniz:
storage.Store(conditions, (item) => Download(item))
Bu nedenle, depolama, temsilciyi yalnızca gerekirse değerlendirerek Koşullara bağlı olarak indirme işlemini gerçekleştirecektir.
Temsilcilerin kullanımı
Array.Sort (T [] dizisi, Karşılaştırma karşılaştırması), List.Sort (Karşılaştırma karşılaştırması), vb. İçindeki karşılaştırma parametresi
Bildiğim kadarıyla delegeler işlev işaretçilerine dönüştürülebilir. Bu, işlev işaretçileri alan yerel kodla birlikte çalışırken hayatı ÇOK kolaylaştırır, çünkü orijinal programcı bunun gerçekleşmesi için herhangi bir hazırlık yapmamış olsa bile, etkin bir şekilde nesne yönelimli olabilirler.
Temsilciler, bir yöntemi referansıyla çağırmak için kullanılır. Örneğin:
delegate void del_(int no1,int no2);
class Math
{
public static void add(int x,int y)
{
Console.WriteLine(x+y);
}
public static void sub(int x,int y)
{
Console.WriteLine(x-y);
}
}
class Program
{
static void Main(string[] args)
{
del_ d1 = new del_(Math.add);
d1(10, 20);
del_ d2 = new del_(Math.sub);
d2(20, 10);
Console.ReadKey();
}
}