मैं एक सामान्य कंटेनर ऑब्जेक्ट (किया गया; कोई समस्या नहीं) बनाने की कोशिश कर रहा हूं जिसे गहरा क्लोन किया जा सकता है। इसका मतलब है कि इसे अपनी निहित वस्तुओं को गहरा क्लोन करना है, और यही वह है जो मुझे समस्याएं पैदा कर रहा है। यहाँ कुछ कोड है:
public abstract class VehiclePart {
public abstract T cloneTypesafe<T>()
where T : VehiclePart, new() // L1
}
public class Gearstick : VehiclePart { // L2
public Gearstick() { }
public override T cloneTypesafe<T>() {
var res2 = new Gearstick();
return res2; // L3
return (T)res2; // L4
}
}
यह इस (टिप्पणी L3) को यह कहते हुए खारिज कर देता है कि "एलडीबी.प्रोग्राम.गियरस्टिक' को 'टी' में निहित रूप से परिवर्तित नहीं किया जा सकता है", लेकिन इसका कोई मतलब नहीं है क्योंकि टी स्पष्ट रूप से वाहनपार्ट (लाइन एल 1) से लिया गया है, और गियरस्टिक स्पष्ट रूप से वाहनपार्ट से लिया गया है। (पंक्ति L2), इसलिए रूपांतरण पूरी तरह से कानूनी होना चाहिए।
यहां तक कि अगर मेरे पास एक स्पष्ट कलाकार था (लाइन एल 4) यह खुश नहीं है ("एलडीबी। प्रोग्राम। गियरस्टिक' को 'टी' में परिवर्तित नहीं कर सकता"), तो समस्या क्या है और मैं इसे कैसे ठीक करूं? (मैं प्रतिबिंब का उपयोग नहीं करना चाहता, जो समान प्रश्नों के उत्तर में एक सामान्य सुझाव प्रतीत होता है। मैंने ICloneable का उपयोग न करने के लिए कई टिप्पणियां पढ़ी हैं)।
4 जवाब
तो समस्या क्या है
आपकी विधि का हस्ताक्षर मुझे आपके कोड को निम्नानुसार कॉल करने की अनुमति देता है:
CarWindow myCarWindow = myGearstick.cloneTypesafe<CarWindow>();
यह एक वैध कॉल है, क्योंकि CarWindow
, VehiclePart
का एक उपप्रकार है। फिर भी, यह स्पष्ट होना चाहिए कि यह कॉल निरर्थक है।
और मैं इसे कैसे ठीक करूं?
C# 9.0 या नए के साथ, आप सहसंयोजक वापसी प्रकारों का उपयोग कर सकते हैं, देखें गुरु स्ट्रॉन का उत्तर।
यदि आप पुराने संस्करणों के साथ फंस गए हैं, तो संभावित समाधान के लिए Jamiec's answer देखें। वैकल्पिक रूप से, आप चिंताओं को अलग करने के लिए विधि को अपने IDeepCloneable<T>
इंटरफ़ेस में निकाल सकते हैं:
public interface IDeepCloneable<T>
{
T CloneTypesafe();
}
public class Gearstick : VehiclePart, IDeepCloneable<Gearstick>
{
public Gearstick CloneTypesafe() { ... }
}
ध्यान दें, जैसा कि जैमीक ने टिप्पणियों में बताया है, टाइप सिस्टम आपको निरर्थक घोषणाएं करने से नहीं रोकेगा, जैसे कि public class Gearstick : VehiclePart, IDeepClonable<Windscreen>
।
इसके लिए काम करने के लिए (मुझे लगता है) आपने उम्मीद की थी, आपके पास अमूर्त वर्ग पर सामान्य परिभाषा होनी चाहिए
public abstract class VehiclePart<T> where T: new() {
public abstract T cloneTypesafe();
}
public class Gearstick : VehiclePart<Gearstick> { // L2
public Gearstick() { }
public override Gearstick cloneTypesafe() {
var res2 = new Gearstick();
return res2;
}
}
यह जेनरिक का दुरुपयोग है। यदि आप जेनरिक का उपयोग करते हैं, तो आप कह रहे हैं कि विधि का कॉलर किसी भी प्रकार से गुजर सकता है (कुछ बाधाओं के साथ), और आपकी विधि अभी भी काम करेगी। स्पष्ट रूप से यहाँ ऐसा नहीं है। आपकी cloneTypesafe
विधि Gearstick
में केवल काम करेगी यदि T
Gearstick
है। अगर T
है, उदा. Engine
, या Wheel
, तो कास्ट विफल हो जाएगी।
cloneTypesafe
को वास्तव में "उस वर्ग के प्रकार" को वापस करना चाहिए, लेकिन हमारे पास सी # में यह कहने का कोई तरीका नहीं है। हालांकि आप इसे एक कामकाज के रूप में कर सकते हैं:
public abstract class VehiclePart<T>
where T : VehiclePart<T>, new(){ // implementers are supposed to replace T with their class
public abstract T cloneTypesafe();
}
// you are not "forced" to say ": VehiclePart<Gearstick>", hence why this is only a workaround
public class Gearstick : VehiclePart<Gearstick> {
public override Gearstick cloneTypesafe() {
var res2 = new Gearstick();
// copy some properties...
return res2;
}
}
C#9 के साथ आप यहां जेनरिक की आवश्यकता को हटा सकते हैं और सहसंयोजक वापसी प्रकार:
public abstract class VehiclePart
{
public abstract VehiclePart cloneTypesafe();
}
public class Gearstick : VehiclePart {
public Gearstick() { }
public override Gearstick cloneTypesafe()
{
return new Gearstick(); // your actual implementation
}
}
संबंधित सवाल
नए सवाल
c#
C # (उच्चारण "तेज देखें") Microsoft द्वारा विकसित एक उच्च स्तरीय, सांख्यिकीय रूप से टाइप किया हुआ, बहु-प्रतिमान प्रोग्रामिंग भाषा है। C # कोड आमतौर पर Microsoft के .NET परिवार के टूल और रन-टाइम को लक्षित करता है, जिसमें .NET फ्रेमवर्क, .NET कोर और Xamarin अन्य शामिल हैं। C # या C # के औपचारिक विनिर्देश में लिखे गए कोड के बारे में प्रश्नों के लिए इस टैग का उपयोग करें।