में ईवेंट और प्रतिनिधि contravariance this question की जांच करते समय मुझे उत्सुकता है कि सी # 4.0 में नई कॉन्वर्सिस/contravariance सुविधाओं को कैसे प्रभावित करेगा।.NET 4.0 और C# 4.0
बीटा 1 में, सी # सीएलआर से असहमत प्रतीत होता है। में वापस सी # 3.0, यदि आप था:
public event EventHandler<ClickEventArgs> Click;
... और फिर कहीं और आप था:
button.Click += new EventHandler<EventArgs>(button_Click);
... संकलक barf क्योंकि वे असंगत प्रतिनिधि प्रकार रहे हैं। लेकिन सी # 4.0 में, यह ठीक से संकलित करता है, क्योंकि सीएलआर 4.0 में टाइप पैरामीटर अब in
के रूप में चिह्नित किया गया है, इसलिए यह contravariant है, और इसलिए संकलक मल्टीकास्ट प्रतिनिधि +=
काम करेगा।
यहाँ मेरी परीक्षा है:
public class ClickEventArgs : EventArgs { }
public class Button
{
public event EventHandler<ClickEventArgs> Click;
public void MouseDown()
{
Click(this, new ClickEventArgs());
}
}
class Program
{
static void Main(string[] args)
{
Button button = new Button();
button.Click += new EventHandler<ClickEventArgs>(button_Click);
button.Click += new EventHandler<EventArgs>(button_Click);
button.MouseDown();
}
static void button_Click(object s, EventArgs e)
{
Console.WriteLine("Button was clicked");
}
}
लेकिन हालांकि यह संकलित है, यह क्रम में काम नहीं करता है (ArgumentException
: प्रतिनिधि एक ही प्रकार के होना चाहिए)।
यह ठीक है अगर आप केवल दो प्रतिनिधि प्रकारों में से एक जोड़ते हैं। लेकिन मल्टीकास्ट में दो अलग-अलग प्रकार के संयोजन अपवाद का कारण बनता है जब दूसरा जोड़ा जाता है।
मुझे लगता है कि यह बीटा 1 में सीएलआर में एक बग है (संकलक का व्यवहार उम्मीदपूर्वक सही दिखता है)। रिलीज़ उम्मीदवार के लिए
अद्यतन:
ऊपर कोड नहीं रह गया है संकलित करता है। यह होना चाहिए कि प्रतिनिधि प्रकार में TEventArgs
का contravariance वापस ले लिया गया है, इसलिए अब प्रतिनिधि के पास .NET 3.5 की समान परिभाषा है।
है, बीटा मैं कम से रहा होगा देखा:
public delegate void EventHandler<in TEventArgs>(object sender, TEventArgs e);
अब यह करने के लिए वापस आ गया है:
public delegate void EventHandler<TEventArgs>(object sender, TEventArgs e);
लेकिन Action<T>
प्रतिनिधि पैरामीटर T
अभी भी contravariant है:
public delegate void Action<in T>(T obj);
वही Func<T>
केके लिए जाता हैकॉन्वर्सेंट होने के नाते।
यह समझौता बहुत समझ में आता है, जब तक हम मानते हैं कि मल्टीकास्ट प्रतिनिधियों का प्राथमिक उपयोग घटनाओं के संदर्भ में है। मैंने व्यक्तिगत रूप से पाया है कि मैं कभी भी घटनाओं को छोड़कर मल्टीकास्ट प्रतिनिधियों का उपयोग नहीं करता हूं।
तो मुझे लगता है कि सी # कोडिंग मानकों को अब एक नया नियम अपनाया जा सकता है: बहुविकल्पीय प्रतिनिधियों को कॉन्वर्सिस/contravariance से संबंधित कई प्रतिनिधि प्रकारों से नहीं बनाते हैं। और यदि आपको नहीं पता कि इसका क्या अर्थ है, तो सुरक्षित पक्ष पर होने वाली घटनाओं के लिए Action
का उपयोग करने से बचें।
बेशक, यह निष्कर्ष the original question that this one grew from के लिए निहितार्थ हैं ...
Thoiugh दिलचस्प सवाल है? –
मुझे आश्चर्य है कि इस छेद ने सी # टीम के नोटिस से बच निकला, जेनेरिक प्रतिनिधियों के लिए भिन्नता शुरू करने के बाद पहली चीजों में से एक होना चाहिए, है ना? सी # 5 इसे भी प्रदर्शित करता है (क्लियर संस्करण वही है)। – nawfal