2011-06-05 14 views
7

यदि मैं सी # में एक इंटरफ़ेस घोषित करता हूं, तो क्या कोई तरीका है कि मैं स्पष्ट रूप से घोषणा कर सकता हूं कि इंटरफ़ेस एक संदर्भ प्रकार है जो किसी भी प्रकार का कार्यान्वयन करता है?निर्दिष्ट करें कि एक इंटरफ़ेस केवल संदर्भ प्रकारों द्वारा लागू किया जा सकता है C#

कारण मैं ऐसा करना चाहता हूं ताकि जहां भी मैं टाइप पैरामीटर के रूप में इंटरफ़ेस का उपयोग करूँ, मुझे यह निर्दिष्ट करने की आवश्यकता नहीं है कि कार्यान्वयन प्रकार को संदर्भ प्रकार भी होना चाहिए।

मैं क्या हासिल करना चाहते हैं का उदाहरण:

public interface IInterface 
{ 
    void A(); 
    int B { get; } 
} 

public class UsingType<T> where T : IInterface 
{ 
    public void DoSomething(T input) 
    { 
     SomeClass.AnotherRoutine(input); 
    } 
} 

public class SomeClass 
{ 
    public static void AnotherRoutine<T>(T input) 
     where T : class 
    { 
     // Do whatever... 
    } 
} 

SomeClass.AnotherRoutine() के तर्क के लिए एक संदर्भ प्रकार होना आवश्यक है के रूप में, मैं यहाँ एक संकलक त्रुटि जहाँ मैं विधि कॉल मिल जाएगा पता चलता है कि मैं T मजबूर UsingType की घोषणा में संदर्भ प्रकार (where T : IInterface, class) होने के लिए। क्या कोई तरीका है कि मैं इसे पहले ही इंटरफ़ेस स्तर पर लागू कर सकता हूं?

public interface IInterface : class 

काम नहीं करता है (जाहिर है) लेकिन शायद एक ही चीज़ को पूरा करने का दूसरा तरीका है?

+0

ऐसा लगता है कि प्रकार एक कार्यान्वयन विस्तार होगा, जो इंटरफ़ेस पहली जगह में सारण करने का प्रयास करता है। मैं उत्सुक हूँ; आप केवल संदर्भ प्रकार कार्यान्वयन की अनुमति क्यों देना चाहते हैं? –

+0

मुझे नहीं लगता कि ऐसा करने का कोई तरीका है, लेकिन क्या वास्तव में यह है कि आपके 'उपयोग प्रकार <>' वर्ग (एसएस) पर अतिरिक्त 'कहां' खंड जोड़ने के लिए और अधिक काम है? – Cameron

+0

@Ed: मेरे विशिष्ट मामले में, मेरे पास एक इंटरफ़ेस 'आईईएनटीटीआई' है जिसे मैंने अपनी सभी व्यावसायिक संस्थाओं को लागू करने दिया। इकाई फ्रेमवर्क मांग करता है कि सभी इकाई प्रकार संदर्भ प्रकार हैं, इसलिए ईएफ के साथ सभी इंटरैक्शन के लिए यह आवश्यक है। चूंकि मुझे पता है कि मैं किसी भी इकाई प्रकार नहीं चाहता जो संदर्भ प्रकार नहीं हैं, मैं पहले से ही इंटरफ़ेस पर निर्दिष्ट करना चाहता हूं। –

उत्तर

0

http://msdn.microsoft.com/en-us/library/d5x73970.aspx। ऐसा लगता है कि आप इसे "वर्ग" निर्दिष्ट कर सकते हैं, जिसका अर्थ संदर्भ प्रकार है।

+0

सच है, लेकिन यह नहीं है कि ओपी क्या पूछ रहा है (वह पहले से ही प्रकार की बाधाओं का उपयोग कर रहा है) – aL3891

+0

ओह, आप सही हैं। मुझे पढ़ने के लिए सीखना है। – SirPentor

0

मुझे नहीं लगता कि आप दुर्भाग्य से इस तरह इंटरफेस को प्रतिबंधित कर सकते हैं। msdn इंटरफेस के अनुसार किसी भी प्रकार, दोनों structs और वर्गों द्वारा कार्यान्वित किया जा सकता है:/

+0

सामान्य इंटरफेस, हाँ - लेकिन क्या इंटरफ़ेस पर एक प्रकार की बाधा लागू करने का कोई तरीका है? –

+0

मुझे यकीन नहीं है कि मैं भेद को समझता हूं, लेकिन मेरे ज्ञान के लिए एक इंटरफ़ेस पर इस तरह के प्रतिबंधों को रखना संभव नहीं है। क्या आप टाइप बाधाओं के साथ देख रहे समस्याओं पर विस्तार कर सकते हैं? यह मेरे लिए सबसे अच्छा समाधान प्रतीत होता है :) – aL3891

3

यदि आप किसी इंटरफ़ेस के नीचे कुछ गुजर रहे हैं, तो यहां तक ​​कि यदि आपके पास इंटरफ़ेस को लागू करने वाला मान प्रकार है तो यह बॉक्सिंग हो जाएगा इंटरफ़ेस और संदर्भ प्रकार की तरह व्यवहार करें (क्योंकि इसे किसी संदर्भ प्रकार के अंदर बॉक्स किया गया है)।

interface IFoo { 
    int Value { get; set; } 
} 

struct Foo : IFoo { 
    public int Value { get; set; } 
} 

प्रभाव जब एक मान प्रकार के रूप में इस्तेमाल का निरीक्षण करें:

var a = new Foo() { Value = 3 }; 
var b = a; // copies value 
b.Value = 4; 
Console.WriteLine("a has {0}", a.Value); //output: a has 3 
Console.WriteLine("b has {0}", b.Value); //output: b has 4 

अब देखो क्या जब आप इसे इंटरफ़ेस करने के लिए डाली होता है:

var a = new Foo() { Value = 3 } as IFoo; //boxed 
var b = a; // copies reference 
b.Value = 4; 
Console.WriteLine("a has {0}", a.Value); //output: a has 4 
Console.WriteLine("b has {0}", b.Value); //output: b has 4 

तो यह है कि क्या कोई फर्क नहीं पड़ता एक संरचना या वर्ग इंटरफ़ेस लागू करता है। यदि इंटरफ़ेस में डाला जाता है और फिर इंटरफ़ेस के नीचे पारित किया जाता है, तो यह संदर्भ प्रकार के रूप में व्यवहार करेगा।

संपादित: तो इन अपनी आवश्यकताओं कर रहे हैं ...

अनुबंध एक्स के लिए:

  1. अगर एक struct/लागू करता है एक संकलन त्रुटि फेंक सकता है विरासत में एक्स
  2. एक्स एक अमूर्त वर्ग नहीं है।

ठीक है, तो आप बस अटक जाते हैं, क्योंकि वे एक-दूसरे से विरोधाभास करते हैं।

  • यदि संकलन लागू होता है/अनुबंध प्राप्त होता है तो संकलन त्रुटि प्राप्त करने का एकमात्र तरीका यह है कि यह एक सार वर्ग है।
  • चूंकि आप विरासत विकल्पों को खोलने के लिए एक अमूर्त वर्ग का उपयोग नहीं कर सकते हैं, तो आपको एक इंटरफ़ेस का उपयोग करना होगा।
  • नियम लागू करने का एकमात्र तरीका है कि एक स्ट्रक्चर इंटरफ़ेस को कार्यान्वित नहीं कर सकता है, रन-टाइम के दौरान होगा।

बाधा where T: class, IFoo का उपयोग हर समय भी काम नहीं करेगा। (समान Foo और IFoo ऊपर के आधार पर) अगर मैं इस विधि था:

static void DoSomething<T>(T foo) where T: class, IFoo { 
    foo.Value += 1; 
    Console.WriteLine("foo has {0}", foo.Value); 
} 

तो यह इस परिस्थिति में एक संकलन त्रुटि फेंक होगा:

var a = new Foo(){ Value = 3 }; 
DoSomething(a); 

लेकिन यह इस परिस्थिति में ठीक काम करेगा :

var a = new Foo(){ Value = 3} as IFoo; //boxed 
DoSomething(a); 

तो जहाँ तक मेरा सवाल है, where T: class, IFoo शैली बाधा का उपयोग करें, और तब यह कोई बात नहीं हो सकता है अगर एक struct कार्यान्वयन इंटरफ़ेस को जब तक यह बॉक्स किया गया हो। एक बॉक्सिंग संरचना पारित होने पर ईएफ की जांच करने पर निर्भर करता है। शायद यह काम करेगा।

यह काम नहीं करता है, तो कम से कम सामान्य बाधा आप हिस्सा तरह से वहाँ हो जाता है, और आप जाँच कर सकते हैं foo.GetType().IsValueType (ऊपर मेरी DoSomething विधि की चर्चा करते हुए) और बॉक्सिंग structs के मामले को संभालने के लिए एक ArgumentException फेंक देते हैं।

+0

मुझे पता है कि इससे कोई फर्क पड़ता है, और मैं यहां क्या करना चाहता हूं, कार्यान्वयन प्रकार को एक संदर्भ प्रकार के रूप में मजबूर करना है, यानी अपना पहला कोड उदाहरण संकलन विफल करें (मुझे दे रहा है एक त्रुटि है कि 'Foo' संदर्भ प्रकार होना चाहिए, या कुछ)। दूसरे शब्दों में, मेरी चिंता यह नहीं है कि "क्या होता है यदि कोई संरचना मेरे इंटरफ़ेस को लागू करती है?", लेकिन "मैं कैसे सुनिश्चित करूं कि कोई संरचना कभी नहीं करेगी?"। –

0

म्यूटेबल structs के मुक्केबाजी व्यवहार interfaces के रूप में डाला निश्चित रूप से परेशान हो सकता है। मुझे नहीं पता कि सभी structs पर एक प्रतिबंध आवश्यक होगा, यद्यपि। ऐसे कई मामले हैं जहां एक क्लास ऑब्जेक्ट को लपेटने के लिए एक अपरिवर्तनीय संरचना हो सकती है (उदाहरण के लिए एक शब्दकोश जैसे कुछ को लागू करने का एक तरीका जो गणना के कई तरीकों का समर्थन करता है, शब्दकोश होगा। केयस और डिक्शनरी। दोनों ही संरचनाएं, प्रत्येक में एक शब्दकोश का संदर्भ होता है, और प्रत्येक एक विशेष GetEnumerator विधि प्रदान करता है; शब्दकोश इस तरह लागू नहीं किया जाता है, लेकिन यह एक खराब पैटर्न नहीं है)। ऐसे पैटर्न में ऐसे मामलों में मुक्केबाजी से बच सकते हैं जहां कोई ऑब्जेक्ट पर GetEnumerator को सीधे कॉल करता है (जैसे vb.net और C# दोनों अपने बतख-टाइप किए गए फ़ोरैच लूप के साथ करते हैं); क्योंकि संरचनाएं अपरिवर्तनीय हैं, यहां तक ​​कि मुक्केबाजी होने पर भी यह एक सहीता के बजाए एक प्रदर्शन मुद्दा है।

संबंधित मुद्दे

 संबंधित मुद्दे