क्या एक स्पष्ट टाइपकास्ट के साथ एक व्युत्पन्न वर्ग संदर्भ के लिए बेस क्लास ऑब्जेक्ट असाइन करना संभव है?


88

क्या यह स्पष्ट है कि C # में एक स्पष्ट टाइपकास्ट के साथ एक व्युत्पन्न वर्ग संदर्भ के लिए एक बेस क्लास ऑब्जेक्ट असाइन करना संभव है।

मैंने इसकी कोशिश की है और यह एक रन-टाइम त्रुटि पैदा करता है।

जवाबों:


98

नहीं। एक व्युत्पन्न वर्ग का एक संदर्भ वास्तव में व्युत्पन्न वर्ग (या अशक्त) की एक आवृत्ति का उल्लेख करना चाहिए। अन्यथा आप इसे व्यवहार करने की उम्मीद कैसे करेंगे?

उदाहरण के लिए:

object o = new object();
string s = (string) o;
int i = s.Length; // What can this sensibly do?

यदि आप आधार प्रकार के उदाहरण को व्युत्पन्न प्रकार में परिवर्तित करने में सक्षम होना चाहते हैं, तो मेरा सुझाव है कि आप एक उपयुक्त व्युत्पन्न प्रकार का उदाहरण बनाने के लिए एक विधि लिखें। या अपने वंश वृक्ष को फिर से देखें और फिर से नया स्वरूप देने की कोशिश करें ताकि आपको पहली बार में ऐसा करने की आवश्यकता न हो।


72
@ माइक: कोड ठीक संकलित करता है। हालांकि यह निष्पादन समय पर गिर जाता है :)
जॉन स्कीट

1
तब क्या होता है जब हम बेस बी = नया व्युत्पन्न () लिखते हैं; ? क्या यह आधार और व्युत्पन्न वर्ग दोनों के लिए वस्तुओं का निर्माण करेगा?
आशिफ नतालिया

3
@ एकी: नहीं, यह एक प्रकार की एक वस्तु बनाता है Derived, लेकिन आप एक Derivedसंदर्भ के रूप में एक Baseसंदर्भ का इलाज कर सकते हैं ।
जॉन स्कीट

तो क्या इन दोनों कथनों के परिणामी वस्तु में कोई अंतर है? आधार b = नया आधार () और आधार b = नया व्युत्पन्न ()? एक के बाद एक का उपयोग करने का क्या लाभ है?
आशिफ नतालिया

4
@ अकी: हाँ, एक का एक उदाहरण बनाता है Base, और दूसरे का एक उदाहरण बनाता है Derived। यदि आप उस वर्चुअल विधि को कहते हैं bजिस पर Derivedआपको ओवरराइड किया गया था , तो आपको Derivedइसका उदाहरण देखने पर व्यवहार दिखाई देगा Derived। लेकिन स्टैक ओवरफ्लो कमेंट थ्रेड में विवरण में जाना वास्तव में उचित नहीं है - आपको वास्तव में एक अच्छी सी # पुस्तक या ट्यूटोरियल पढ़ना चाहिए, क्योंकि यह बहुत ही मौलिक सामग्री है।
जॉन स्कीट

46

नहीं, यह संभव नहीं है क्योंकि इसे व्युत्पन्न वर्ग के संदर्भ में निर्दिष्ट किया जाए, जैसे कि "बेस क्लास व्युत्पन्न वर्ग के लिए पूरी तरह से सक्षम विकल्प है, यह वह सब कुछ कर सकता है जो व्युत्पन्न वर्ग कर सकता है", जो सामान्य पेशकश में व्युत्पन्न वर्गों के बाद से सच नहीं है। उनके आधार वर्ग की तुलना में अधिक कार्यक्षमता (कम से कम, यह उत्तराधिकार के पीछे का विचार है)।

आप मानों को कॉपी करते हुए बेस क्लास ऑब्जेक्ट को पैरामीटर के रूप में लेते हुए व्युत्पन्न वर्ग में एक कंस्ट्रक्टर लिख सकते हैं।

कुछ इस तरह:

public class Base {
    public int Data;

    public void DoStuff() {
        // Do stuff with data
    }
}

public class Derived : Base {
    public int OtherData;

    public Derived(Base b) {
        this.Data = b.Data;
        OtherData = 0; // default value
    }

    public void DoOtherStuff() {
        // Do some other stuff
    }
}

उस स्थिति में आप आधार वस्तु की नकल करेंगे और व्युत्पन्न सदस्यों के लिए डिफ़ॉल्ट मानों के साथ पूरी तरह कार्यात्मक व्युत्पन्न वर्ग वस्तु प्राप्त करेंगे। इस तरह से आप जॉन स्कीट द्वारा बताई गई समस्या से भी बच सकते हैं:

Base b = new Base();//base class
Derived d = new Derived();//derived class

b.DoStuff();    // OK
d.DoStuff();    // Also OK
b.DoOtherStuff();    // Won't work!
d.DoOtherStuff();    // OK

d = new Derived(b);  // Copy construct a Derived with values of b
d.DoOtherStuff();    // Now works!

23

मेरे पास यह समस्या थी और इसे एक विधि जोड़कर हल किया गया जो एक प्रकार का पैरामीटर लेता है और वर्तमान वस्तु को उस प्रकार में परिवर्तित करता है।

public TA As<TA>() where TA : Base
{
    var type = typeof (TA);
    var instance = Activator.CreateInstance(type);

     PropertyInfo[] properties = type.GetProperties();
     foreach (var property in properties)
     {
         property.SetValue(instance, property.GetValue(this, null), null);
     }

     return (TA)instance;
}

इसका मतलब है कि आप इसे इस तरह से कोड में उपयोग कर सकते हैं:

var base = new Base();
base.Data = 1;
var derived = base.As<Derived>();
Console.Write(derived.Data); // Would output 1

आपको वर्तमान वर्ग के प्रकार (आधार वर्ग) का उपयोग करना चाहिए और गुण प्राप्त करने और सेट करने के लिए क्योंकि वे मान हैं जो आप व्युत्पन्न वर्ग के लिए मैप करना चाहते हैं।
बोफोला

1
यदि आपके पास ऐसे गुण हैं, जो आपको व्युत्पन्न प्रकार में नहीं लिखे जा सकते हैं, तो आपको संभवतः इसमें बदलना चाहिए: अगर (गुण। कनराइट) गुण।
user3478586

10

जैसा कि कई अन्य लोगों ने उत्तर दिया है, नहीं।

मैं उन दुर्भाग्यपूर्ण अवसरों पर निम्न कोड का उपयोग करता हूं, जब मुझे आधार प्रकार को एक व्युत्पन्न प्रकार के रूप में उपयोग करने की आवश्यकता होती है। हां यह लिस्कोव सबस्टीट्यूशन सिद्धांत (एलएसपी) का उल्लंघन है और हां ज्यादातर समय हम वंशानुक्रम पर रचना का पक्ष लेते हैं। मार्कस कन्नप्पन जोहानसन को प्रॉप्स जिसका मूल उत्तर इस पर आधारित है।

बेस क्लास में यह कोड:

    public T As<T>()
    {
        var type = typeof(T);
        var instance = Activator.CreateInstance(type);

        if (type.BaseType != null)
        {
            var properties = type.BaseType.GetProperties();
            foreach (var property in properties)
                if (property.CanWrite)
                    property.SetValue(instance, property.GetValue(this, null), null);
        }

        return (T) instance;
    }

की अनुमति देता है:

    derivedObject = baseObect.As<derivedType>()

चूंकि यह प्रतिबिंब का उपयोग करता है, इसलिए यह "महंगा" है। तदनुसार उपयोग करें।


मैंने अभी-अभी यह कोशिश की, और यह पता चला कि इसे और सुधारा जा सकता है, स्पष्ट परिचालक (और निहित परिचालक के रूप में अच्छी तरह से) को ओवरलोड करके .. लेकिन - कंपाइलर इसकी अनुमति नहीं देगा: user-defined conversions to or from a base class are not allowed मैं इसके कारणों को देखता हूं, लेकिन निराश हूं, जैसा कि अगर यह अनुमति देता तो बहुत मज़ा आता ..
हेनरिक

@MEC: मैंने देखा कि आपने `जहां T: MyBaseClass 'भाग को छोड़ दिया और if (type.BaseType != null)मार्कस कन्नप्पन जोहानसन के ए। के सापेक्ष स्टेटमेंट को जोड़ दिया । वह क्यों है? इसका मतलब है कि यह उन कॉलों में एक प्रकार की अनुमति देगा जो MyBaseClass (या उस मामले के लिए कुछ भी) से व्युत्पन्न नहीं है। मुझे लगता है कि अगर यह myDerivedObject को असाइन किया गया है, तो यह अभी भी एक कंपाइलर त्रुटि का कारण बनेगा, लेकिन अगर यह सिर्फ एक अभिव्यक्ति के रूप में उपयोग किया जाता है, तो यह संकलन करेगा और रन-टाइम पर "myBaseObject" से कॉपी किए गए किसी भी डेटा के बिना myDerivedObject बनाएँ। मैं उस के लिए एक उपयोग के मामले की कल्पना नहीं कर सकता।
टॉम

@ उलट, देर से जवाब, लेकिन सोचा कि यह अभी भी उपयोगी हो सकता है। आपके सवाल का सबसे अच्छा जवाब शायद यही होगा कि "As" नाम "AsOrDefault" बेहतर होगा। अनिवार्य रूप से हम इस परिणाम को ले सकते हैं और इसकी तुलना एक डिफ़ॉल्ट से कर सकते हैं जैसे हम Linq के SingleOrDefault या FirstOrDefault का उपयोग करते समय करते हैं।
MEC

7

नहीं, यह संभव नहीं है, इसलिए आपकी रनटाइम त्रुटि।

लेकिन आप एक व्युत्पन्न वर्ग के उदाहरण को बेस क्लास प्रकार के एक चर में असाइन कर सकते हैं।


7

JsonConvert (टाइपकास्ट के बजाय) के साथ समाधान

आज मैंने उसी मुद्दे का सामना किया और मुझे समस्या का सरल और त्वरित समाधान मिला JsonConvert

var base = new BaseClass();
var json = JsonConvert.SerializeObject(base);
DerivedClass derived = JsonConvert.DeserializeObject<DerivedClass>(json);

मैंने विस्तार विधियों के साथ फिर से इसका उत्तर दिया। हां, यह जवाब है।
पैट्रिक नॉट

5

जैसा कि यहां सभी ने कहा, यह सीधे तौर पर संभव नहीं है।

मैं जिस विधि को पसंद करता हूं और साफ नहीं करता, वह है AutoMapper जैसे ऑब्जेक्ट मैपर का उपयोग करना ।

यह संपत्तियों को एक उदाहरण से दूसरे में कॉपी करने का काम करेगा (जरूरी नहीं कि एक ही प्रकार)।


3

@ Ybo के उत्तर पर विस्तार करना - यह संभव नहीं है क्योंकि आपके पास आधार वर्ग का उदाहरण वास्तव में व्युत्पन्न वर्ग का उदाहरण नहीं है। यह केवल आधार वर्ग के सदस्यों के बारे में जानता है, और व्युत्पन्न वर्ग के लोगों के बारे में कुछ भी नहीं जानता है।

इसका कारण यह है कि आप व्युत्पन्न वर्ग का एक उदाहरण बेस क्लास के उदाहरण के लिए डाल सकते हैं, क्योंकि व्युत्पन्न वर्ग वास्तव में पहले से ही बेस क्लास का एक उदाहरण है, क्योंकि इसमें पहले से ही सदस्य हैं। इसके विपरीत नहीं कहा जा सकता है।


3

आप एक वैरिएबल डाल सकते हैं जो बेस क्लास के रूप में टाइप की गई क्लास के लिए टाइप किया जाता है; हालाँकि, आवश्यकता से यह एक रनटाइम जाँच करेगा, यह देखने के लिए कि इसमें शामिल वास्तविक वस्तु सही प्रकार की है या नहीं।

एक बार बनाने के बाद, किसी वस्तु के प्रकार को बदला नहीं जा सकता है (कम से कम, यह समान आकार नहीं हो सकता है)। हालाँकि, आप एक उदाहरण को परिवर्तित कर सकते हैं, दूसरे प्रकार का एक नया उदाहरण बना सकते हैं - लेकिन आपको मैन्युअल रूप से रूपांतरण कोड लिखना होगा।


2

नहीं, यह संभव नहीं है।

एक परिदृश्य पर विचार करें जहां एक ACBus बेस क्लास बस का एक व्युत्पन्न वर्ग है। ACBus में TurnOnAC और TurnOffAC जैसी विशेषताएं हैं जो ACState नामक फ़ील्ड पर काम करती हैं। TurnOnAC ACState को चालू करता है और TurnOffAC ACState को बंद करने के लिए सेट करता है। यदि आप Bus पर TurnOnAC और TurnOffAC सुविधाओं का उपयोग करने का प्रयास करते हैं, तो इसका कोई मतलब नहीं है।


2
class Program
{
    static void Main(string[] args)
    {
        a a1 = new b();  
        a1.print();  
    }
}
class a
{
    public a()
    {
        Console.WriteLine("base class object initiated");
    }
    public void print()
    {
        Console.WriteLine("base");
    }
}
class b:a
{
    public b()
    {
        Console.WriteLine("child class object");
    }
    public void print1()
    {
        Console.WriteLine("derived");
    }
}

}

जब हम चाइल्ड क्लास ऑब्जेक्ट बनाते हैं, बेस क्लास ऑब्जेक्ट ऑटो होता है, तो बेस क्लास रेफरेंस वेरिएबल चाइल्ड क्लास ऑब्जेक्ट को इंगित कर सकता है।

लेकिन इसके विपरीत नहीं क्योंकि चाइल्ड क्लास रेफरेंस वैरिएबल बेस क्लास ऑब्जेक्ट को इंगित नहीं कर सकता क्योंकि कोई चाइल्ड क्लास ऑब्जेक्ट नहीं बना है।

और यह भी ध्यान दें कि बेस क्लास रेफरेंस वेरिएबल को केवल बेस क्लास मेंबर कह सकते हैं।


2

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

तो यहाँ है कि मैं यह कैसे किया। एक छोटा कोड नमूना मेरे स्पष्टीकरण का पालन करेगा।

  1. आधार वर्ग से अपनी वस्तु का एक उदाहरण बनाएं और तदनुसार उसे पॉपुलेट करें।

  2. न्यूटनसॉफ्ट जोंस के "जोंस्कॉनवर्ट" वर्ग का उपयोग करते हुए, उस वस्तु को एक जस स्ट्रिंग में क्रमबद्ध करें।

  3. अब चरण 2 में बनाए गए json स्ट्रिंग के साथ डीसर्लाइज़ करके अपनी सब क्लास ऑब्जेक्ट बनाएं। यह बेस क्लास के सभी गुणों के साथ आपके सब क्लास का एक उदाहरण बनाएगा।

यह एक आकर्षण की तरह काम करता है! तो .. यह कब उपयोगी है? कुछ लोगों ने पूछा कि यह कब समझ में आएगा और इस तथ्य को समायोजित करने के लिए ओपी के स्कीमा को बदलने का सुझाव दिया कि आप मूल रूप से वर्ग विरासत (.Net) के साथ ऐसा नहीं कर सकते।

मेरे मामले में, मेरे पास एक सेटिंग वर्ग है जिसमें एक सेवा के लिए सभी "आधार" सेटिंग्स हैं। विशिष्ट सेवाओं में अधिक विकल्प होते हैं और वे एक अलग DB तालिका से आते हैं, इसलिए उन वर्गों को आधार वर्ग विरासत में मिलता है। उन सभी के पास विकल्पों का एक अलग सेट है। इसलिए जब किसी सेवा के लिए डेटा पुनर्प्राप्त किया जाता है, तो आधार ऑब्जेक्ट की एक आवृत्ति का उपयोग करके मूल्यों को पहले से ही दर्ज करना बहुत आसान होता है। एक विधि एक एकल DB क्वेरी के साथ ऐसा करने के लिए। ठीक इसके बाद, मैं ऊपर उल्लिखित विधि का उपयोग करके उप वर्ग ऑब्जेक्ट बनाता हूं। मैं तब दूसरी क्वेरी बनाता हूं और सब क्लास ऑब्जेक्ट पर सभी डायनामिक वैल्यूज को पॉप्युलेट करता हूं।

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

यह उदाहरण कोड vb.Net है, लेकिन आप आसानी से c # में बदल सकते हैं।

' First, create the base settings object.
    Dim basePMSettngs As gtmaPayMethodSettings = gtmaPayments.getBasePayMethodSetting(payTypeId, account_id)
    Dim basePMSettingsJson As String = JsonConvert.SerializeObject(basePMSettngs, Formatting.Indented)

    ' Create a pmSettings object of this specific type of payment and inherit from the base class object
    Dim pmSettings As gtmaPayMethodAimACHSettings = JsonConvert.DeserializeObject(Of gtmaPayMethodAimACHSettings)(basePMSettingsJson)

C # और Newtonsoft.Json का उपयोग करना var destObject = JsonConvert.DeserializeObject<DestinationType>(JsonConvert.SerializeObject(srcObject));:। मैं इसका उपयोग केवल यूनिट परीक्षण और अन्य गैर-उत्पादन "हैकिंग" के लिए करूंगा!
ThinkOfaNumber

2

आप एक एक्सटेंशन्स का उपयोग कर सकते हैं:

public static void CopyOnlyEqualProperties<T>(this T objDest, object objSource) where T : class
    {
        foreach (PropertyInfo propInfo in typeof(T).GetProperties())
            if (objSource.GetType().GetProperties().Any(z => z.Name == propInfo.Name && z.GetType() == propInfo.GetType()))
                propInfo.SetValue(objDest, objSource.GetType().GetProperties().First(z => z.Name == propInfo.Name && z.GetType() == propInfo.GetType()).GetValue(objSource));
    }

कोड में:

public class BaseClass
{
  public string test{ get; set;}
}
public Derived : BaseClass
{
//Some properies
}

public void CopyProps()
{
   BaseClass baseCl =new BaseClass();
   baseCl.test="Hello";
   Derived drv=new Derived();
   drv.CopyOnlyEqualProperties(baseCl);
   //Should return Hello to the console now in derived class.
   Console.WriteLine(drv.test);

}

1

हो सकता है कि पुन: आविष्कार न किया जाए, लेकिन मैं एक व्युत्पन्न वस्तु पर कोड चलाने में सक्षम था, जिसका आधार दिया गया था। यह निश्चित रूप से मुझे अधिक पसंद है, लेकिन यह काम करता है:

public static T Cast<T>(object obj)
{
    return (T)obj;
}

...

//Invoke parent object's json function
MethodInfo castMethod = this.GetType().GetMethod("Cast").MakeGenericMethod(baseObj.GetType());
object castedObject = castMethod.Invoke(null, new object[] { baseObj });
MethodInfo jsonMethod = baseObj.GetType ().GetMethod ("ToJSON");
return (string)jsonMethod.Invoke (castedObject,null);

1

आप जेनेरिक का उपयोग करके ऐसा कर सकते हैं।

public class BaseClass
{
    public int A { get; set; }
    public int B { get; set; }
    private T ConvertTo<T>() where T : BaseClass, new()
    {
         return new T
         {
             A = A,
             B = B
         }
    }

    public DerivedClass1 ConvertToDerivedClass1()
    {
         return ConvertTo<DerivedClass1>();
    }

    public DerivedClass2 ConvertToDerivedClass2()
    {
         return ConvertTo<DerivedClass2>();
    }
}

public class DerivedClass1 : BaseClass
{
    public int C { get; set; }
}

public class DerivedClass2 : BaseClass
{
    public int D { get; set; }
}

इस दृष्टिकोण का उपयोग करके आपको तीन लाभ मिलते हैं।

  1. आप कोड की नकल नहीं कर रहे हैं
  2. आप प्रतिबिंब का उपयोग नहीं कर रहे हैं (जो धीमा है)
  3. आपके सभी रूपांतरण एक ही स्थान पर हैं

1

मुझे पता है कि यह पुराना है, लेकिन मैंने इसे काफी समय से सफलतापूर्वक उपयोग किया है।

   private void PopulateDerivedFromBase<TB,TD>(TB baseclass,TD derivedclass)
    {
        //get our baseclass properties
        var bprops = baseclass.GetType().GetProperties();
        foreach (var bprop in bprops)
        {
            //get the corresponding property in the derived class
            var dprop = derivedclass.GetType().GetProperty(bprop.Name);
            //if the derived property exists and it's writable, set the value
            if (dprop != null && dprop.CanWrite)
                dprop.SetValue(derivedclass,bprop.GetValue(baseclass, null),null);
        }
    } 

1

मैंने पिछले उत्तरों के कुछ अंशों (उन लेखकों के लिए धन्यवाद) को संयोजित किया और एक साधारण स्थिर वर्ग को दो विधियों के साथ रखा, जिनका हम उपयोग कर रहे हैं।

हां, यह सरल है, नहीं, यह सभी परिदृश्यों को कवर नहीं करता है, हाँ इसे विस्तारित किया जा सकता है और बेहतर बनाया जा सकता है, नहीं, यह बिल्कुल सही नहीं है, हाँ यह संभवतः अधिक कुशल बनाया जा सकता है, नहीं यह कटा हुआ ब्रेड के बाद से सबसे बड़ी बात नहीं है, हाँ वहाँ हैं फुल-ऑन स्ट्रॉन्ग नगेट पैकेज ऑब्जेक्ट मैपर आउट आउट जो कि भारी उपयोग, आदि आदि के लिए बेहतर है, यादा यादा - लेकिन यह हमारी बुनियादी जरूरतों के लिए काम करता है हालांकि :)

और निश्चित रूप से यह किसी भी वस्तु से किसी भी वस्तु के मूल्यों को मैप करने की कोशिश करेगा, व्युत्पन्न या नहीं (केवल सार्वजनिक गुण जिन्हें पाठ्यक्रम का नाम दिया गया है - बाकी को अनदेखा करता है)।

उपयोग:

SesameStreetCharacter puppet = new SesameStreetCharacter() { Name = "Elmo", Age = 5 };

// creates new object of type "RealPerson" and assigns any matching property 
// values from the puppet object 
// (this method requires that "RealPerson" have a parameterless constructor )
RealPerson person = ObjectMapper.MapToNewObject<RealPerson>(puppet);

// OR

// create the person object on our own 
// (so RealPerson can have any constructor type that it wants)
SesameStreetCharacter puppet = new SesameStreetCharacter() { Name = "Elmo", Age = 5 };
RealPerson person = new RealPerson("tall") {Name = "Steve"};

// maps and overwrites any matching property values from 
// the puppet object to the person object so now our person's age will get set to 5 and
// the name "Steve" will get overwritten with "Elmo" in this example
ObjectMapper.MapToExistingObject(puppet, person);

स्टेटिक उपयोगिता श्रेणी:

public static class ObjectMapper
{
    // the target object is created on the fly and the target type 
    // must have a parameterless constructor (either compiler-generated or explicit) 
    public static Ttarget MapToNewObject<Ttarget>(object sourceobject) where Ttarget : new()
    {
        // create an instance of the target class
        Ttarget targetobject = (Ttarget)Activator.CreateInstance(typeof(Ttarget));

        // map the source properties to the target object
        MapToExistingObject(sourceobject, targetobject);

        return targetobject;
    }

    // the target object is created beforehand and passed in
    public static void MapToExistingObject(object sourceobject, object targetobject)
    {
        // get the list of properties available in source class
        var sourceproperties = sourceobject.GetType().GetProperties().ToList();

        // loop through source object properties
        sourceproperties.ForEach(sourceproperty => {

            var targetProp = targetobject.GetType().GetProperty(sourceproperty.Name);

            // check whether that property is present in target class and is writeable
            if (targetProp != null && targetProp.CanWrite)
            {
                // if present get the value and map it
                var value = sourceobject.GetType().GetProperty(sourceproperty.Name).GetValue(sourceobject, null);
                targetobject.GetType().GetProperty(sourceproperty.Name).SetValue(targetobject, value, null);
            }
        });
    }
}

1

आप एक कॉपी कंस्ट्रक्टर का उपयोग कर सकते हैं, जो इंस्टेंस कंस्ट्रक्टर को तुरंत इनवाइट करता है, या यदि आपका इंस्टेंस कंस्ट्रक्टर असाइनमेंट्स से ज्यादा करता है, तो कॉपी कंस्ट्रक्टर को इनकमिंग वैल्यूस को इंस्टाल करने के लिए असाइन करें।

class Person
{
    // Copy constructor 
    public Person(Person previousPerson)
    {
        Name = previousPerson.Name;
        Age = previousPerson.Age;
    }

    // Copy constructor calls the instance constructor.
    public Person(Person previousPerson)
        : this(previousPerson.Name, previousPerson.Age)
    {
    }

    // Instance constructor.
    public Person(string name, int age)
    {
        Name = name;
        Age = age;
    }

    public int Age { get; set; }

    public string Name { get; set; }
}

इस उदाहरण के लिए कंस्ट्रक्टर के तहत Microsoft C # दस्तावेज़ीकरण का संदर्भ दिया था, जो पिछले समय में यह समस्या थी।


0

एक अन्य समाधान विस्तार विधि को जोड़ना है जैसे:

 public static void CopyProperties(this object destinationObject, object sourceObject, bool overwriteAll = true)
        {
            try
            {
                if (sourceObject != null)
                {
                    PropertyInfo[] sourceProps = sourceObject.GetType().GetProperties();
                    List<string> sourcePropNames = sourceProps.Select(p => p.Name).ToList();
                    foreach (PropertyInfo pi in destinationObject.GetType().GetProperties())
                    {
                        if (sourcePropNames.Contains(pi.Name))
                        {
                            PropertyInfo sourceProp = sourceProps.First(srcProp => srcProp.Name == pi.Name);
                            if (sourceProp.PropertyType == pi.PropertyType)
                                if (overwriteAll || pi.GetValue(destinationObject, null) == null)
                                {
                                    pi.SetValue(destinationObject, sourceProp.GetValue(sourceObject, null), null);
                                }
                        }
                    }
                }
            }
            catch (ApplicationException ex)
            {
                throw;
            }
        }

तब प्रत्येक व्युत्पन्न वर्ग में एक निर्माता होता है जो आधार वर्ग को स्वीकार करता है:

  public class DerivedClass: BaseClass
    { 
        public DerivedClass(BaseClass baseModel)
        {
            this.CopyProperties(baseModel);
        }
    }

यह वैकल्पिक रूप से गंतव्य संपत्तियों को भी अधिलेखित कर देगा यदि पहले से सेट (शून्य नहीं) या नहीं।


0

क्या यह स्पष्ट है कि C # में एक स्पष्ट टाइपकास्ट के साथ एक व्युत्पन्न वर्ग संदर्भ के लिए एक बेस क्लास ऑब्जेक्ट असाइन करना संभव है।

न केवल स्पष्ट, बल्कि अंतर्निहित रूपांतरण भी संभव है।

सी # भाषा ऐसे रूपांतरण ऑपरेटरों को अनुमति नहीं देती है, लेकिन आप फिर भी उन्हें शुद्ध सी # का उपयोग करके लिख सकते हैं और वे काम करते हैं। ध्यान दें कि वर्ग जो निहित रूपांतरण ऑपरेटर (परिभाषित करता है Derived) और वर्ग जो ऑपरेटर का उपयोग करता है ( Program) अलग विधानसभाओं में परिभाषित किया जाना चाहिए (उदाहरण के लिए Derivedवर्ग एक में है library.dllजो द्वारा संदर्भित है program.exeयुक्त Programवर्ग)।

//In library.dll:
public class Base { }

public class Derived {
    [System.Runtime.CompilerServices.SpecialName]
    public static Derived op_Implicit(Base a) {
        return new Derived(a); //Write some Base -> Derived conversion code here
    }

    [System.Runtime.CompilerServices.SpecialName]
    public static Derived op_Explicit(Base a) {
        return new Derived(a); //Write some Base -> Derived conversion code here
    }
}

//In program.exe:
class Program {
    static void Main(string[] args) {
        Derived z = new Base(); //Visual Studio can show squiggles here, but it compiles just fine.
    }
}

जब आप विज़ुअल स्टूडियो में प्रोजेक्ट रेफरेंस का उपयोग करते हुए लाइब्रेरी का संदर्भ देते हैं, तो जब आप अंतर्निहित रूपांतरण का उपयोग करते हैं, तो वीएस स्क्विगल्स दिखाता है, लेकिन यह ठीक-ठीक संकलन करता है। यदि आप केवल संदर्भ देते हैं library.dll, तो कोई स्किगल नहीं हैं।


यह कैसा काला जादू है ?! इसके अलावा, "Derived z = new Base ()" BaseCls baseObj "करने में मेरी सहायता कैसे करता है? DerivedCls व्युत्पन्नObj; व्युत्पन्नओज = (DerivedCls) baseObj" (ओपी का क्यू)? इसके अलावा, System.Runtime.CompilerServices.SpecialNameगुण क्या करता है? हर संस्करण के लिए डॉक्स जल्द से जल्द उपलब्ध (2.0) से "वर्तमान संस्करण" (4.6? "किसी को भी? किसी को भी?) यह नहीं कहता कि यह क्या करता है, लेकिन कहते हैं कि" विशेष नामकरण वर्ग वर्तमान में .NET में उपयोग नहीं किया गया है। फ्रेमवर्क, लेकिन भविष्य के उपयोग के लिए आरक्षित है। " देखें: [लिंक] ( msdn.microsoft.com/en-us/library/ms146064(v=vs.100).aspx )।
टॉम

> "यह कैसा काला जादू है?" इसे .Net फ्रेमवर्क (CLR, IL, BCL) कहा जाता है। IL, C # और VB भाषाओं का फीचर सेट एक जैसा नहीं है। VB में ऐसे फीचर्स हैं जिनका C # सपोर्ट नहीं करता है। IL में ऐसे फीचर हैं जो C # सपोर्ट नहीं करते हैं। C # में प्रतिबंध हैं जो मनमाने ढंग से होते हैं और अंतर्निहित IL (जैसे where T : Delegateया पैराट्राइज्ड गुण उर्फ ​​इंडेक्सर्स आदि) आदि में मौजूद नहीं होते हैं ।
आर्क-कुन

> इसके अलावा, कैसे "व्युत्पन्न z = नया आधार ()" मुझे करने में मदद करता है "BaseCls baseObj; DerivedCls व्युत्पन्न; derObj = (DerivedCls) baseObj "(ओपी के क्यू)?" यह बस करता है। यह ओपी के प्रश्न को हल करता है। और आपको स्पष्ट कलाकारों की भी आवश्यकता नहीं है।
-कुन

> what does System.Runtime.CompilerServices.SpecialName Attribute do?- इसका उपयोग उच्च-स्तरीय .Net भाषाओं के कुछ विशेष सुविधा निर्माणों द्वारा निर्मित विधियों को चिह्नित करने के लिए किया जाता है: संपत्ति एक्सेसर्स, ईवेंट एक्सेसर्स, कंस्ट्रक्टर्स, ऑपरेटर, इंडेक्सर्स, जब तक कि आईएल विधि चिह्नित specialnameनहीं होती है, तब तक यह नहीं देखा जाएगा। संपत्ति / घटना / निर्माणकर्ता के रूप में और इसे सिर्फ एक सामान्य विधि के रूप में मान्यता दी जाएगी। इस विशेषता के साथ उचित रूप से नामित विधियों को मैन्युअल रूप से चिह्नित करना संकलक के काम को थोड़ा सा मैन्युअल रूप से करना है।
आर्क-कुन

VB.Net में पावर ऑपरेटर है। C # नहीं करता है। VB.Net में उपयोग के लिए आप C # में एक पावर ऑपरेटर को कैसे अधिभारित करेंगे? बस एक op_Exponentविधि को परिभाषित करें और इसे specialnameविशेषता के साथ चिह्नित करें ।
आर्क-कुन


0

व्युत्पन्न वस्तु में सभी आधार गुणों को जोड़ने का सबसे अच्छा तरीका है, लागत में प्रतिबिंब का उपयोग करना। विधियों या उदाहरणों को बनाए बिना, इस कोड को आज़माएं।

    public Derived(Base item) :base()
    {

        Type type = item.GetType();

        System.Reflection.PropertyInfo[] properties = type.GetProperties();
        foreach (var property in properties)
        {
            try
            {
                property.SetValue(this, property.GetValue(item, null), null);
            }
            catch (Exception) { }
        }

    }

0

मैं असहमत हूं कि यह संभव नहीं है। आप इसे इस तरह से कर सकते हैं:

public class Auto 
{ 
    public string Make {get; set;}
    public string Model {get; set;}
}

public class Sedan : Auto
{ 
    public int NumberOfDoors {get; set;}
}

public static T ConvertAuto<T>(Sedan sedan) where T : class
{
    object auto = sedan;
    return (T)loc;
}

उपयोग:

var sedan = new Sedan();
sedan.NumberOfDoors = 4;
var auto = ConvertAuto<Auto>(sedan);

var auto =अभी भी टाइप हैsedan
बेंडेको

0

इसे मैंने खेतों के लिए हल किया है। आप चाहें तो संपत्तियों के माध्यम से एक ही पुनरावृत्ति कर सकते हैं। आप nullआदि के लिए कुछ जांच करना चाहते हैं, लेकिन यह विचार है।

 public static DerivedClass ConvertFromBaseToDerived<BaseClass, DerivedClass>(BaseClass baseClass)
            where BaseClass : class, new()
            where DerivedClass : class, BaseClass, new()
        {
            DerivedClass derived = (DerivedClass)Activator.CreateInstance(typeof(DerivedClass));
            derived.GetType().GetFields().ToList().ForEach(field =>
            {
                var base_ = baseClass.GetType().GetField(field.Name).GetValue(baseClass);
                field.SetValue(derived, base_);

            });

            return derived;
        }

0

आप बस बेस ऑब्जेक्ट को JSON में अनुक्रमित कर सकते हैं और फिर व्युत्पन्न वस्तु के लिए इसे डीरियलाइज़ कर सकते हैं।


0

ट्रेडिशनल सीन्स में नहीं ... जोंस में कनवर्ट करें, फिर अपनी वस्तु, और बूम, के लिए! ऊपर जेसी के पास पहले जवाब था, लेकिन इन विस्तार विधियों का उपयोग नहीं किया, जो इस प्रक्रिया को इतना आसान बनाते हैं। एक्सटेंशन विधियों के एक जोड़े बनाएँ:

    public static string ConvertToJson<T>(this T obj)
    {
        return JsonConvert.SerializeObject(obj);
    }
    public static T ConvertToObject<T>(this string json)
    {
        if (string.IsNullOrEmpty(json))
        {
            return Activator.CreateInstance<T>();
        }
        return JsonConvert.DeserializeObject<T>(json);
    }

उन्हें हमेशा के लिए अपने टूलबॉक्स में रखें, फिर आप हमेशा ऐसा कर सकते हैं:

var derivedClass = baseClass.ConvertToJson().ConvertToObject<derivedClass>();

आह, JSON की शक्ति।

इस दृष्टिकोण के साथ कुछ जोड़े हैं: हम वास्तव में एक नई वस्तु का निर्माण कर रहे हैं, न कि कास्टिंग, जो कोई फर्क नहीं पड़ सकता है। निजी क्षेत्रों को स्थानांतरित नहीं किया जाएगा, मापदंडों वाले निर्माणकर्ताओं को नहीं बुलाया जाएगा, आदि यह संभव है कि कुछ बच्चे को सौंपा नहीं जाएगा। JsonConvert द्वारा धाराओं को सहज रूप से नियंत्रित नहीं किया जाता है। हालांकि, अगर हमारी कक्षा निजी क्षेत्रों और कंस्ट्रक्टर्स पर भरोसा नहीं करती है, तो यह बिना मानचित्रण और निर्माणकर्ताओं को बुलाए कक्षा से कक्षा तक डेटा स्थानांतरित करने का एक बहुत प्रभावी तरीका है, जो कि मुख्य कारण है कि हम पहली जगह में डालना चाहते हैं।


यह वह नहीं करता है जो ओपी ने पूछा था। आप जो कर रहे हैं वह गलत प्रकार की मूल वस्तु के डेटा का उपयोग करके चर के लिए सही प्रकार की एक नई वस्तु का निर्माण कर रहा है। यह काम कर सकता है या नहीं भी कर सकता है, लेकिन किसी भी तरह से, यह निश्चित रूप से बेस क्लास प्रकार की एक वस्तु को व्युत्पन्न प्रकार के एक चर में असाइन नहीं कर रहा है।
लसे वी। कार्लसन जू

मैंने सवाल का जवाब दिया: क्या एक स्पष्ट टाइपकास्ट के साथ एक व्युत्पन्न वर्ग के संदर्भ के लिए एक बेस क्लास ऑब्जेक्ट निर्दिष्ट करना संभव है? कहकर नहीं। मैं एक विकल्प प्रदान कर रहा हूं जो बिल्कुल काम करता है और जेनरिक की तुलना में कम भ्रमित है। जैसा कि ऊपर कई बार निरूपित किया गया है, यह एक आधार वर्ग से व्युत्पन्न वर्ग के गुणों को असाइन करने वाले मुद्दों का कारण बन सकता है, हालांकि, यह ठीक है कि अगर यह संभव हो तो यह कैसे काम करेगा (और एपिस में करता है)। सिर्फ इसलिए कि मेरे उत्तर का उपयोग "गलत" प्रकार से किया जा सकता है, इसका मतलब यह नहीं है कि इसका उपयोग "सही" प्रकार के लिए नहीं किया जा सकता है। @ LasseV.Karlsen कृपया अपनी नकारात्मक रेटिंग वापस लें।
पैट्रिक नॉट

यहाँ के अधिकांश जवाबों के विपरीत, जो डेज़ी श्रृंखला JsonConverts, मैं दिखाता हूँ कि कैसे नल को भी संभालना है।
पैट्रिक नॉट

-1

नहीं, यह प्रश्न देखें जो मैंने पूछा - जेनेरिक का उपयोग करके .NET में Upcasting

सबसे अच्छा तरीका है कि क्लास पर एक डिफ़ॉल्ट कंस्ट्रक्टर बनाया जाए, निर्माण किया जाए और फिर एक Initialiseविधि को कॉल किया जाए

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.