[नोट: इस सवाल का मूल शीर्षक " C (ish) स्टाइल यूनियन में C # " था लेकिन जैसा कि जेफ की टिप्पणी ने मुझे सूचित किया, जाहिर है कि इस संरचना को 'भेदभावपूर्ण संघ' कहा जाता है]
इस प्रश्न की वाचालता को क्षमा करें।
एसओ में पहले से ही मेरे लिए कुछ इसी तरह के लगने वाले सवाल हैं, लेकिन वे यूनियन के मेमोरी सेविंग फायदों पर ध्यान केंद्रित करते हैं या इसे इंटरोप के जरिए इस्तेमाल करते हैं। ऐसे प्रश्न का एक उदाहरण यहाँ दिया गया है ।
संघ प्रकार की चीज पाने की मेरी इच्छा कुछ अलग है।
मैं इस समय कुछ कोड लिख रहा हूं जो उन वस्तुओं को उत्पन्न करता है जो इस तरह से दिखते हैं
public class ValueWrapper
{
public DateTime ValueCreationDate;
// ... other meta data about the value
public object ValueA;
public object ValueB;
}
सुंदर जटिल सामान मुझे लगता है कि आप सहमत होंगे। बात यह है कि ValueA
केवल कुछ निश्चित प्रकार के हो सकते हैं (चलो कहते हैं string
, int
और Foo
(जो कि एक वर्ग है) और ValueB
प्रकारों का एक और सेट हो सकता है। मुझे इन मूल्यों को ऑब्जेक्ट्स के रूप में व्यवहार करना पसंद नहीं है (मैं चाहता हूं कि गर्म स्नेगल महसूस हो। एक प्रकार की सुरक्षा के साथ कोडिंग)।
इसलिए मैंने इस तथ्य को व्यक्त करने के लिए एक तुच्छ छोटे आवरण वर्ग को लिखने के बारे में सोचा था कि ValueA तार्किक रूप से एक विशेष प्रकार का एक संदर्भ है। मैंने कक्षा को फोन किया Union
क्योंकि मैं सी में यूनियन कॉन्सेप्ट की याद दिलाने की कोशिश कर रहा हूं।
public class Union<A, B, C>
{
private readonly Type type;
public readonly A a;
public readonly B b;
public readonly C c;
public A A{get {return a;}}
public B B{get {return b;}}
public C C{get {return c;}}
public Union(A a)
{
type = typeof(A);
this.a = a;
}
public Union(B b)
{
type = typeof(B);
this.b = b;
}
public Union(C c)
{
type = typeof(C);
this.c = c;
}
/// <summary>
/// Returns true if the union contains a value of type T
/// </summary>
/// <remarks>The type of T must exactly match the type</remarks>
public bool Is<T>()
{
return typeof(T) == type;
}
/// <summary>
/// Returns the union value cast to the given type.
/// </summary>
/// <remarks>If the type of T does not exactly match either X or Y, then the value <c>default(T)</c> is returned.</remarks>
public T As<T>()
{
if(Is<A>())
{
return (T)(object)a; // Is this boxing and unboxing unavoidable if I want the union to hold value types and reference types?
//return (T)x; // This will not compile: Error = "Cannot cast expression of type 'X' to 'T'."
}
if(Is<B>())
{
return (T)(object)b;
}
if(Is<C>())
{
return (T)(object)c;
}
return default(T);
}
}
इस वर्ग का उपयोग कर ValueWrapper अब इस तरह दिखता है
public class ValueWrapper2
{
public DateTime ValueCreationDate;
public Union<int, string, Foo> ValueA;
public Union<double, Bar, Foo> ValueB;
}
जो कुछ ऐसा है जो मैं प्राप्त करना चाहता था लेकिन मुझे एक महत्वपूर्ण तत्व याद आ रहा है - वह है कंपाइलर लागू प्रकार की जाँच जब कॉल करना निम्नलिखित कोड के रूप में है और जैसा कार्य करता है
public void DoSomething()
{
if(ValueA.Is<string>())
{
var s = ValueA.As<string>();
// .... do somethng
}
if(ValueA.Is<char>()) // I would really like this to be a compile error
{
char c = ValueA.As<char>();
}
}
IMO यह वैल्यू पूछने के लिए मान्य नहीं है अगर यह एक है char
क्योंकि इसकी परिभाषा स्पष्ट रूप से कहती है कि यह नहीं है - यह एक प्रोग्रामिंग त्रुटि है और मैं चाहूंगा कि संकलक इस पर उठाएं । [इसके अलावा अगर मुझे यह सही लग सकता है तो (उम्मीद है) मुझे भी अच्छा लगेगा - जो एक वरदान होगा।]
इसे प्राप्त करने के लिए मैं संकलक को बताना चाहूंगा कि प्रकार T
ए, बी या सी में से एक हो सकता है
public bool Is<T>() where T : A
or T : B // Yes I know this is not legal!
or T : C
{
return typeof(T) == type;
}
क्या किसी के पास कोई विचार है अगर मैं जो हासिल करना चाहता हूं वह संभव है? या मैं इस वर्ग को पहली जगह लिखने के लिए सिर्फ सादा बेवकूफ हूं?
अग्रिम में धन्यवाद।
StructLayout(LayoutKind.Explicit)
औरFieldOffset
। यह संदर्भ प्रकारों के साथ नहीं किया जा सकता है, निश्चित रूप से। आप जो कर रहे हैं वह सी यूनियन की तरह नहीं है।