Not
Bu sayfaya erişim yetkilendirme gerektiriyor. Oturum açmayı veya dizinleri değiştirmeyi deneyebilirsiniz.
Bu sayfaya erişim yetkilendirme gerektiriyor. Dizinleri değiştirmeyi deneyebilirsiniz.
Bir temsilciye bir yöntem atadığınızda, kovaryans ve ters değişken , bir temsilci türünü yöntem imzası ile eşleştirme esnekliği sağlar. Kovaryans, bir metodun temsilcide tanımlanandan daha fazla türetilmiş dönüş türüne sahip olmasına olanak tanır. Contravariance, temsilci türündekilerden daha az türetilmiş parametre türlerine sahip bir yönteme izin verir.
Örnek 1: Kovaryans
Açıklama
Bu örnek, temsilcilerin, temsilci imzasında belirtilen dönüş türlerinden türetilen dönüş türlerine sahip yöntemlerle nasıl kullanılabileceğini gösterir.
DogsHandler tarafından döndürülen veri türü, temsilcide tanımlanan Dogs türünden türetilen Mammals türündedir.
Kod
class Mammals {}
class Dogs : Mammals {}
class Program
{
// Define the delegate.
public delegate Mammals HandlerMethod();
public static Mammals MammalsHandler()
{
return null;
}
public static Dogs DogsHandler()
{
return null;
}
static void Test()
{
HandlerMethod handlerMammals = MammalsHandler;
// Covariance enables this assignment.
HandlerMethod handlerDogs = DogsHandler;
}
}
Örnek 2: Kontravaryans
Açıklama
Bu örnek, temsilcilerin, parametre türleri temsilci imzasındaki parametre türünün temel türleri olan yöntemlerle nasıl kullanılabileceğini gösterir. Contravariance ile ayrı işleyiciler yerine tek bir olay işleyicisi kullanabilirsiniz. Aşağıdaki örnekte iki temsilci kullanılır:
Bir anahtar olayının imzasını tanımlayan özel
KeyEventHandlertemsilci. İmzası:public delegate void KeyEventHandler(object sender, KeyEventArgs e)Fare olayının imzasını tanımlayan özel
MouseEventHandlertemsilci. İmzası:public delegate void MouseEventHandler(object sender, MouseEventArgs e)
Örnek, parametresi olan bir EventArgs olay işleyicisi tanımlar ve bunu hem anahtar hem de fare olaylarını işlemek için kullanır. Bu, EventArgs'ın, örnekte tanımlanan hem özel KeyEventArgs hem de MouseEventArgs sınıflarının temel türü olması nedeniyle çalışır. Contravariance, türetilmiş tür parametreleri sağlayan olaylar için kullanılacak bir temel tür parametresi kabul eden bir yöntem sağlar.
Bu örnekte contravariance nasıl çalışır?
Bir olaya abone olduğunuzda, derleyici olay işleyici yönteminizin olayın temsilci imzası ile uyumlu olup olmadığını denetler. Kontravaryans ile:
-
KeyDownolayı,KeyEventArgsöğesini alan bir yöntem bekler. -
MouseClickolayı,MouseEventArgsöğesini alan bir yöntem bekler. - Yönteminiz
MultiHandlertemel türünüEventArgsalır. -
KeyEventArgsveMouseEventArgsher ikisi deEventArgsöğesinden devraldığından,EventArgstüründeki bir yönteme güvenli bir şekilde geçirilebilir. - Derleyici güvenli olduğundan bu atamaya
MultiHandlerizin verir; herhangi birEventArgsörnekle çalışabilir.
Bu, kontravaryansın uygulamalı halidir: "daha özel" (türetilmiş tür) bir parametre beklenirken "daha genel" (temel tür) bir parametreye sahip bir yöntem kullanabilirsiniz.
Kod
// Custom EventArgs classes to demonstrate the hierarchy
public class KeyEventArgs(string keyCode) : EventArgs
{
public string KeyCode { get; set; } = keyCode;
}
public class MouseEventArgs(int x, int y) : EventArgs
{
public int X { get; set; } = x;
public int Y { get; set; } = y;
}
// Define delegate types that match the Windows Forms pattern
public delegate void KeyEventHandler(object sender, KeyEventArgs e);
public delegate void MouseEventHandler(object sender, MouseEventArgs e);
// A simple class that demonstrates contravariance with events
public class Button
{
// Events that expect specific EventArgs-derived types
public event KeyEventHandler? KeyDown;
public event MouseEventHandler? MouseClick;
// Method to simulate key press
public void SimulateKeyPress(string key)
{
Console.WriteLine($"Simulating key press: {key}");
KeyDown?.Invoke(this, new KeyEventArgs(key));
}
// Method to simulate mouse click
public void SimulateMouseClick(int x, int y)
{
Console.WriteLine($"Simulating mouse click at ({x}, {y})");
MouseClick?.Invoke(this, new MouseEventArgs(x, y));
}
}
public class Form1
{
private Button button1;
public Form1()
{
button1 = new Button();
// Event handler that accepts a parameter of the base EventArgs type.
// This method can handle events that expect more specific EventArgs-derived types
// due to contravariance in delegate parameters.
// You can use a method that has an EventArgs parameter,
// although the KeyDown event expects the KeyEventArgs parameter.
button1.KeyDown += MultiHandler;
// You can use the same method for an event that expects
// the MouseEventArgs parameter.
button1.MouseClick += MultiHandler;
}
// Event handler that accepts a parameter of the base EventArgs type.
// This works for both KeyDown and MouseClick events because:
// - KeyDown expects KeyEventHandler(object sender, KeyEventArgs e)
// - MouseClick expects MouseEventHandler(object sender, MouseEventArgs e)
// - Both KeyEventArgs and MouseEventArgs derive from EventArgs
// - Contravariance allows a method with a base type parameter (EventArgs)
// to be used where a derived type parameter is expected
private void MultiHandler(object sender, EventArgs e)
{
Console.WriteLine($"MultiHandler called at: {DateTime.Now:HH:mm:ss.fff}");
// You can check the actual type of the event args if needed
switch (e)
{
case KeyEventArgs keyArgs:
Console.WriteLine($" - Key event: {keyArgs.KeyCode}");
break;
case MouseEventArgs mouseArgs:
Console.WriteLine($" - Mouse event: ({mouseArgs.X}, {mouseArgs.Y})");
break;
default:
Console.WriteLine($" - Generic event: {e.GetType().Name}");
break;
}
}
public void DemonstrateEvents()
{
Console.WriteLine("Demonstrating contravariance in event handlers:");
Console.WriteLine("Same MultiHandler method handles both events!\n");
button1.SimulateKeyPress("Enter");
button1.SimulateMouseClick(100, 200);
button1.SimulateKeyPress("Escape");
button1.SimulateMouseClick(50, 75);
}
}
Kontravarians ile ilgili önemli noktalar
// Demonstration of how contravariance works with delegates:
//
// 1. KeyDown event signature: KeyEventHandler(object sender, KeyEventArgs e)
// where KeyEventArgs derives from EventArgs
//
// 2. MouseClick event signature: MouseEventHandler(object sender, MouseEventArgs e)
// where MouseEventArgs derives from EventArgs
//
// 3. Our MultiHandler method signature: MultiHandler(object sender, EventArgs e)
//
// 4. Contravariance allows us to use MultiHandler (which expects EventArgs)
// for events that provide more specific types (KeyEventArgs, MouseEventArgs)
// because the more specific types can be safely treated as their base type.
//
// This is safe because:
// - The MultiHandler only uses members available on the base EventArgs type
// - KeyEventArgs and MouseEventArgs can be implicitly converted to EventArgs
// - The compiler knows that any EventArgs-derived type can be passed safely
Bu örneği çalıştırdığınızda, aynı MultiHandler yöntemin hem tuş hem de fare olaylarını başarıyla işlediğini ve değişken karşıtının daha esnek ve yeniden kullanılabilir olay işleme kodunu nasıl etkinleştirdiğini gösterir.