दिलचस्प पोस्ट
फ़ंक्शन ओवरलोडिंग और पीएचपी में ओवरराइड करना क्या है? जावा बाइटकोड में स्केल के गुण कैसे संकलित किए जाते हैं? हेरोकी पर 4 चित्रों को लोड नहीं किया जा रहा है क्यों नल रिक्त झूठी के बराबर नहीं है एक सीमा के बिना एक WPF विंडो कैसे बना सकता है जिसे केवल एक पकड़ के माध्यम से बदल दिया जा सकता है? Admob कार्यान्वयन त्रुटि Analytics Google API त्रुटि 403: "प्रयोक्ता के पास कोई भी Google Analytics खाता नहीं है" जब UITextField पहले उत्तरदाता बन जाता है तो UIScrollView स्क्रोलिंग को अक्षम करें एसवीजी का इस्तेमाल करते हुए वेब पेज पर लिखावट का पाठ कैसे बदलना है? अपलोड किए गए फ़ाइल को एक निर्देशिका में सहेजने से पहले उसका नाम कैसे बदलें? अस्थायी बिंदु अंकगणित सटीक नतीजे का उत्पादन नहीं करते गणित। मैदान (संख्या) बनाम num.toFixed (0) और ब्राउज़र विसंगतियां SQL सर्वर 2005 में एक बयान में दो तालिकाओं को अपडेट करने के लिए कैसे? "PHP घातक त्रुटि: क्लास 'एचटीपीआरएक्वेस्ट' नहीं मिला" स्ट्रिंग के रूप में अपने कच्चे एसक्यूएल क्वेरी को आउटपुट करने के लिए मैं क्वेरी बिल्डर कैसे प्राप्त करूं?

क्यों नहीं ICloneable <टी>?

क्या कोई विशेष कारण है कि एक सामान्य ICloneable<T> मौजूद नहीं है?

यह बहुत अधिक आरामदायक होगा, अगर मुझे इसे हर बार डालने की ज़रूरत नहीं होती तो मैं कुछ क्लोन करता था

वेब के समाधान से एकत्रित समाधान "क्यों नहीं ICloneable <टी>?"

आईसीलाइनेबल को अब एक खराब एपीआई माना जाता है, क्योंकि यह निर्दिष्ट नहीं करता कि परिणाम गहरे या उथले प्रति है। मुझे लगता है यही कारण है कि वे इस इंटरफ़ेस में सुधार नहीं करते हैं।

आप संभवतः एक टाइप क्लोनिंग एक्सटेंशन विधि कर सकते हैं, लेकिन मुझे लगता है कि इसके लिए अलग नाम की आवश्यकता होगी क्योंकि विस्तारित तरीकों की तुलना मूल सड़कों से कम है।

एंड्री के जवाब के अतिरिक्त (जो मैं सहमत हूं, 1) – जब ICloneable किया जाता है, तो आप सार्वजनिक Clone() टाइप करने के लिए ऑब्जेक्ट वापस करने के लिए स्पष्ट कार्यान्वयन भी चुन सकते हैं:

 public Foo Clone() { /* your code */ } object ICloneable.Clone() {return Clone();} 

बेशक सामान्य ICloneable<T> – उत्तराधिकार के साथ एक दूसरा मुद्दा है।

अगर मेरे पास:

 public class Foo {} public class Bar : Foo {} 

और मैंने ICloneable<T> लागू किया है, तो क्या मैं ICloneable<Foo> लागू कर सकता हूं? ICloneable<Bar> ? आप बहुत सी समान इंटरफेस को लागू करना शुरू करते हैं … किसी कलाकार से तुलना करें … और क्या यह वाकई बहुत बुरा है?

मुझे यह पूछने की ज़रूरत है कि आप इसे लागू करने के अलावा इंटरफेस के साथ क्या करेंगे? इंटरफेस आमतौर पर केवल तब उपयोगी होते हैं जब आप इसे डालें (यानी यह वर्ग का समर्थन 'आईबीआर') करता है, या उसके पास मानदंड या सेटर्स हैं (यानी मैं 'आईबीआर' लेता हूं)। आईसीलाइनेबल के साथ – हम पूरे फ्रेमवर्क के माध्यम से चले गए और एक एकल उपयोग को खोजने में असफल रहे, जहां कहीं भी इसके कार्यान्वयन के अलावा कुछ और था। हम 'असली दुनिया' में किसी भी तरह का उपयोग करने में विफल रहे हैं जो इसे लागू करने के अलावा कुछ भी करता है (~ 60,000 ऐप्स में जिन तक हमें एक्सेस है)।

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

डेविड केन (बीसीएल टीम)

मुझे लगता है कि प्रश्न "क्यों" अनावश्यक है वहाँ बहुत सारे इंटरफेस / वर्ग / आदि हैं … जो बहुत उपयोगी है, लेकिन .NET Frameworku आधार लाइब्रेरी का हिस्सा नहीं है।

लेकिन, मुख्य रूप से आप इसे अपने आप कर सकते हैं

 public interface ICloneable<T> : ICloneable { new T Clone(); } public abstract class CloneableBase<T> : ICloneable<T> where T : CloneableBase<T> { public abstract T Clone(); object ICloneable.Clone() { return this.Clone(); } } public abstract class CloneableExBase<T> : CloneableBase<T> where T : CloneableExBase<T> { protected abstract T CreateClone(); protected abstract void FillClone( T clone ); public override T Clone() { T clone = this.CreateClone(); if ( object.ReferenceEquals( clone, null ) ) { throw new NullReferenceException( "Clone was not created." ); } return clone } } public abstract class PersonBase<T> : CloneableExBase<T> where T : PersonBase<T> { public string Name { get; set; } protected override void FillClone( T clone ) { clone.Name = this.Name; } } public sealed class Person : PersonBase<Person> { protected override Person CreateClone() { return new Person(); } } public abstract class EmployeeBase<T> : PersonBase<T> where T : EmployeeBase<T> { public string Department { get; set; } protected override void FillClone( T clone ) { base.FillClone( clone ); clone.Department = this.Department; } } public sealed class Employee : EmployeeBase<Employee> { protected override Employee CreateClone() { return new Employee(); } } 

यदि आपको इसकी आवश्यकता है तो इंटरफ़ेस को लिखना बहुत आसान है:

 public interface ICloneable<T> : ICloneable where T : ICloneable<T> { new T Clone(); } 

हाल ही में लेख पढ़ना क्यों एक वस्तु की प्रतिलिपि बनाने के लिए एक भयानक बात है? , मुझे लगता है कि इस सवाल के लिए अतिरिक्त क्लैरिफिकेशन की आवश्यकता है। अन्य उत्तर यहां अच्छे सलाह देते हैं, लेकिन फिर भी इसका जवाब पूरा नहीं हुआ है – क्यों नहीं ICloneable<T> ?

  1. प्रयोग

    तो, आपके पास एक ऐसा वर्ग है जो इसे लागू करता है जबकि पहले आपको एक विधि थी जो ICloneable चाहते थे, अब यह ICloneable<T> को स्वीकार करने के लिए सामान्य होना चाहिए। आपको इसे संपादित करना होगा

    उसके बाद, आप एक विधि प्राप्त कर सकते हैं जो जांचता है कि कोई ऑब्जेक्ट is ICloneable अब क्या? आप ऐसा नहीं कर सकते is ICloneable<> और जैसा आप संकलन-प्रकार में ऑब्जेक्ट के प्रकार को नहीं जानते, आप इस विधि को सामान्य नहीं बना सकते पहली वास्तविक समस्या

    तो आपको ICloneable<T> और ICloneable , दोनों को बाद वाले को लागू करने की आवश्यकता है। इस प्रकार एक क्रियान्वयनकर्ता को दोनों विधियों – object Clone() और T Clone() को लागू करने की आवश्यकता होगी। नहीं, धन्यवाद, हमारे पास पहले से ही IEnumerable साथ पर्याप्त मज़ा है

    जैसा कि पहले से ही बताया गया है, विरासत की जटिलता भी है। हालांकि इस समस्या को हल करने के लिए सहानुभूति लग सकता है, एक व्युत्पन्न प्रकार को अपने स्वयं के प्रकार के ICloneable<T> लागू करने की जरूरत है, लेकिन मूल हस्ताक्षर (मूलभूत रूप से = पैरामीटर) के साथ एक विधि पहले से ही है – आधार क्लास का Clone() अपना नया क्लोन पद्धति इंटरफ़ेस स्पष्ट करना व्यर्थ है, आप जो फायदा उठाते हैं ICloneable<T> बनाते समय खो देंगे। तो new कीवर्ड जोड़ें लेकिन यह मत भूलो कि आपको बेस क्लास ' Clone() को भी ओवरराइड करना होगा (कार्यान्वयन सभी व्युत्पन्न कक्षाओं के लिए एक समान रहना होगा, अर्थात प्रत्येक क्लोन पद्धति से समान ऑब्जेक्ट लौटा देना, इसलिए आधार क्लोन विधि होना चाहिए virtual )! लेकिन, दुर्भाग्यवश, आप एक ही हस्ताक्षर के साथ दोनों override और new विधियां नहीं कर सकते। पहला कीवर्ड चुनना, आप उस लक्ष्य को खो देंगे जिसमें आप चाहते थे कि जब आप ICloneable<T> जोड़ते हों दूसरे को चुने जाने पर, आप इंटरफ़ेस को ही तोड़ते हैं, ऐसे तरीकों को बनाते हैं, जिनकी वापसी अलग-अलग वस्तुओं को करना चाहिए।

  2. बिंदु

    आप आराम के लिए ICloneable<T> चाहते हैं, लेकिन आराम से यह नहीं है कि किस इंटरफेस के लिए डिज़ाइन किया गया है, उनका अर्थ (सामान्य ओओपी में) वस्तुओं के व्यवहार को एकजुट करने के लिए है (हालांकि सी # में, बाहरी व्यवहार को एकजुट करना सीमित है, जैसे कि विधि और संपत्तियों, उनके कामकाज नहीं)।

    यदि पहले कारण ने आपको अभी तक आश्वस्त नहीं किया है, तो आप इस बात का ICloneable<T> कर सकते हैं कि ICloneable<T> क्लोन पद्धति से लौटाए गए प्रकार को सीमित करने के लिए प्रतिबंधित रूप से काम भी कर सकता है। हालांकि, गंदा प्रोग्रामर ICloneable<T> को लागू कर सकता है जहां टी उस प्रकार नहीं है जो इसे लागू कर रहा है इसलिए, अपने प्रतिबंध को प्राप्त करने के लिए, आप सामान्य पैरामीटर में एक अच्छी बाधा जोड़ सकते हैं:
    public interface ICloneable<T> : ICloneable where T : ICloneable<T>
    निश्चित रूप से अधिक प्रतिबंधात्मक यह है कि बिना एक, where आप अभी भी उस टी को प्रतिबंधित नहीं कर सकते हैं जो इंटरफ़ेस को लागू कर रहे हैं (आप ICloneable<T> से विभिन्न प्रकार के इसे लागू कर सकते हैं)।

    आप देख सकते हैं, यहां तक ​​कि इस उद्देश्य को प्राप्त नहीं किया जा सकता है (मूल ICloneable भी इस पर असफल रहता है, कोई इंटरफ़ेस वास्तव में लागू करने वाले वर्ग के व्यवहार को सीमित नहीं कर सकता है)

जैसा कि आप देख सकते हैं, यह सामान्य इंटरफ़ेस बनाने से साबित होता है कि यह पूरी तरह से कार्यान्वित करने के लिए कठिन है और यह वास्तव में अनावश्यक और बेकार है।

लेकिन सवाल पर वापस, जो आप वास्तव में चाहते हैं, एक वस्तु क्लोनिंग करते समय आराम करना है। ऐसा करने के दो तरीके हैं:

अतिरिक्त विधियां

 public class Base : ICloneable { public Base Clone() { return this.CloneImpl() as Base; } object ICloneable.Clone() { return this.CloneImpl(); } protected virtual object CloneImpl() { return new Base(); } } public class Derived : Base { public new Derived Clone() { return this.CloneImpl() as Derived; } protected override object CloneImpl() { return new Derived(); } } 

यह समाधान उपयोगकर्ता के लिए आराम और इच्छित व्यवहार दोनों प्रदान करता है, लेकिन यह लागू करने के लिए भी बहुत लंबा है यदि हम वर्तमान प्रकार की "आराम से" विधि वापस नहीं करना चाहते हैं, तो सिर्फ public virtual object Clone()

तो चलिए "परम" समाधान देखें – सी # में हमें वास्तव में आराम देने के लिए क्या मायने रखता है?

एक्सटेंशन तरीकों!

 public class Base : ICloneable { public virtual object Clone() { return new Base(); } } public class Derived : Base { public override object Clone() { return new Derived(); } } public static T Copy<T>(this T obj) where T : class, ICloneable { return obj.Clone() as T; } 

वर्तमान क्लोन पद्धतियों के साथ टकराव न करने के लिए इसका नाम प्रतिलिपि है (संकलक एक्सटेंशन के विस्तार पर प्रकार की अपनी घोषित विधियों को पसंद करता है)। class बाधा गति के लिए है (रिक्त जांच आदि की आवश्यकता नहीं है)।

मुझे उम्मीद है कि इस कारण से स्पष्ट किया गया है कि क्यों नहीं ICloneable<T> हालांकि, यह सिफारिश की जाती है कि ICloneable को लागू न करें।

एक बड़ी समस्या यह है कि वे टी को समान कक्षा के रूप में प्रतिबंधित नहीं कर सके। उदाहरण के लिए आप ऐसा करने से क्या रोकेंगे:

 interface IClonable<T> { T Clone(); } class Dog : IClonable<JackRabbit> { //not what you would expect, but possible JackRabbit Clone() { return new JackRabbit(); } } 

उन्हें पैरामीटर प्रतिबंध की आवश्यकता है जैसे:

 interfact IClonable<T> where T : implementing_type 

हालांकि सवाल बहुत पुराना है (यह उत्तर लिखने से 5 साल) और पहले से ही उत्तर दिया गया था, लेकिन मुझे यह आलेख मिला है इस लेख का जवाब काफी अच्छी तरह से है, इसे यहां देखें

संपादित करें:

यहां आलेख का उद्धरण है जो प्रश्न का उत्तर देता है (पूरा लेख पढ़ना सुनिश्चित करें, इसमें अन्य रोचक बातें शामिल हैं):

माइक्रोसॉफ्ट में नियोजित समय पर ब्रैड अब्राम के 2003 ब्लॉग पोस्ट की ओर इशारा करते हुए इंटरनेट पर कई संदर्भ हैं – जिसमें आईसीएलओनेबल के बारे में कुछ विचार-विमर्श किया गया है। ब्लॉग प्रविष्टि इस पते पर पाई जा सकती है: आईसीलाइनेबल को कार्यान्वित करना भ्रामक खिताब के बावजूद, इस ब्लॉग प्रविष्टि को आईसीएलओनेबल लागू नहीं करने के लिए कहा जाता है, मुख्य रूप से उथले / गहरे भ्रम के कारण। अनुच्छेद एक सीधे सुझाव में समाप्त होता है: यदि आपको एक क्लोनिंग तंत्र की आवश्यकता है, तो अपना क्लोन परिभाषित करें या पद्धति का प्रतिलिपि बनाएं, और सुनिश्चित करें कि आप स्पष्ट रूप से दस्तावेज़ करें कि यह एक गहरी या उथले प्रति है एक उपयुक्त पैटर्न है: public <type> Copy();

यह एक बहुत अच्छा सवाल है … आप अपना स्वयं का बना सकते हैं, हालांकि:

 interface ICloneable<T> : ICloneable { new T Clone ( ); } 

एंड्री कहते हैं कि यह एक खराब एपीआई माना जाता है, लेकिन मैंने इस इंटरफ़ेस को नापसंद बनने के बारे में कुछ नहीं सुना है। और वह कई इंटरफेस को तोड़ देगा … क्लोन विधि को उथले प्रतिलिपि करना चाहिए। यदि ऑब्जेक्ट भी गहरी कॉपी प्रदान करता है, तो एक अतिभारित क्लोन (bool deep) का उपयोग किया जा सकता है।

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

 class C { public C ( C prototype ) { ... } } 

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