मैं .NET .NET / CLR में API वर्जनिंग के बारे में अधिक से अधिक जानकारी एकत्र करना चाहूंगा, और विशेष रूप से कैसे एपीआई क्लाइंट एप्लिकेशन को तोड़ता है या नहीं तोड़ता है। सबसे पहले, कुछ शब्दों को परिभाषित करते हैं:
एपीआई परिवर्तन - किसी भी सार्वजनिक सदस्य सहित एक प्रकार की सार्वजनिक रूप से दिखाई देने वाली परिभाषा में परिवर्तन। इसमें बदलते प्रकार और सदस्य के नाम, प्रकार के आधार प्रकार को बदलना, एक प्रकार के कार्यान्वित इंटरफेस की सूची से इंटरफेस जोड़ना / हटाना, सदस्यों को जोड़ना / हटाना (ओवरलोड सहित), सदस्य दृश्यता बदलना, विधि और प्रकार के मापदंडों को बदलना, डिफ़ॉल्ट मान जोड़ना विधि मापदंडों के लिए, प्रकार और सदस्यों पर विशेषताओं को जोड़ना / हटाना, और प्रकारों और सदस्यों पर सामान्य प्रकार के मापदंडों को जोड़ना / हटाना (क्या मैं कुछ भी जीवित हूं?)। इसमें सदस्य निकायों में कोई भी बदलाव, या निजी सदस्यों में कोई बदलाव शामिल नहीं है (यानी हम इस पर ध्यान नहीं देते)।
बाइनरी-लेवल ब्रेक - एक एपीआई परिवर्तन जो क्लाइंट असेंबली में परिणाम करता है जो कि पुराने संस्करण के खिलाफ संकलित होता है, संभवतः नए संस्करण के साथ लोड नहीं हो रहा है। उदाहरण: बदलती विधि हस्ताक्षर, भले ही इसे पहले की तरह से ही बुलाया जाए (यानी: टाइप करने के लिए शून्य / पैरामीटर डिफ़ॉल्ट मान अधिभार)।
स्रोत-स्तरीय विराम - एक एपीआई परिवर्तन जिसके परिणामस्वरूप मौजूदा कोड को एपीआई के पुराने संस्करण के खिलाफ संकलन करने के लिए लिखा गया है, संभवतः नए संस्करण के साथ संकलन नहीं है। हालाँकि पहले से संकलित क्लाइंट असेंबलियाँ पहले की तरह काम करती हैं। उदाहरण: एक नया अधिभार जोड़ना जो विधि कॉल में अस्पष्टता के परिणामस्वरूप हो सकता है जो कि पिछले अस्पष्ट थे।
स्रोत-स्तरीय शांत शब्दार्थ परिवर्तन - एक एपीआई परिवर्तन जिसके परिणामस्वरूप मौजूदा कोड में एपीआई के पुराने संस्करण के खिलाफ संकलन करने के लिए चुपचाप अपने शब्दार्थ को बदलते हैं, जैसे एक अलग विधि को कॉल करके। हालांकि कोड को बिना किसी चेतावनी / त्रुटियों के संकलित करना जारी रखना चाहिए, और पहले संकलित असेंबलियों को पहले की तरह काम करना चाहिए। उदाहरण: किसी मौजूदा वर्ग पर एक नया इंटरफ़ेस लागू करना जिसके परिणामस्वरूप अधिभार संकल्प के दौरान एक अलग अधिभार चुना जाता है।
अंतिम लक्ष्य संभव के रूप में कई ब्रेकिंग और शांत शब्दार्थ एपीआई परिवर्तनों को सूचीबद्ध करना है, और ब्रेक्जिट के सटीक प्रभाव का वर्णन करना है, और कौन सी भाषाएं हैं और इससे प्रभावित नहीं हैं। उत्तरार्द्ध में विस्तार करने के लिए: जबकि कुछ परिवर्तन सभी भाषाओं को सार्वभौमिक रूप से प्रभावित करते हैं (जैसे कि एक इंटरफ़ेस में एक नया सदस्य जोड़ना किसी भी भाषा में उस इंटरफ़ेस के कार्यान्वयन को तोड़ देगा), कुछ को तोड़ने के लिए नाटक में प्रवेश करने के लिए बहुत विशिष्ट भाषा शब्दार्थ की आवश्यकता होती है। इस सबसे आम तौर पर विधि अधिभार शामिल है, और, सामान्य रूप से, अंतर्निहित प्रकार के रूपांतरणों के साथ कुछ भी करना है। सीएलएस-अनुरूप भाषाओं के लिए यहां तक कि "कम से कम सामान्य भाजक" को परिभाषित करने का कोई भी तरीका प्रतीत नहीं होता है (यानी सीएलआई युक्ति में परिभाषित "सीएलएस उपभोक्ता" के नियमों के अनुसार कम से कम) - हालांकि मैं ' सराहना करेंगे अगर कोई मुझे गलत होने के रूप में यहाँ सही करता है - तो यह भाषा से भाषा में जाना होगा। सबसे अधिक रुचि स्वाभाविक रूप से वे हैं जो बॉक्स से .NET के साथ आते हैं: C #, VB और F #; लेकिन अन्य, जैसे आयरनपाइथन, आयरनरुबी, डेल्फी प्रिज्म आदि भी प्रासंगिक हैं। एक कोने के मामले में जितना अधिक होगा, उतना ही दिलचस्प होगा - सदस्यों को हटाने जैसी चीजें बहुत ही स्व-स्पष्ट हैं, लेकिन उदाहरण के लिए सूक्ष्म बातचीत जैसे कि विधि अधिभार, वैकल्पिक / डिफ़ॉल्ट पैरामीटर, लैम्ब्डा प्रकार का अनुमान, और रूपांतरण ऑपरेटर बहुत आश्चर्यचकित हो सकते हैं कभी कभी।
इसे किकस्टार्ट करने के लिए कुछ उदाहरण:
नई विधि अधिभार जोड़ना
प्रकार: स्रोत-स्तरीय विराम
प्रभावित भाषाएँ: C #, VB, F #
परिवर्तन से पहले एपीआई:
public class Foo
{
public void Bar(IEnumerable x);
}
परिवर्तन के बाद एपीआई:
public class Foo
{
public void Bar(IEnumerable x);
public void Bar(ICloneable x);
}
नमूना ग्राहक कोड परिवर्तन से पहले काम कर रहा है और उसके बाद टूट गया है:
new Foo().Bar(new int[0]);
नए निहित रूपांतरण ऑपरेटर को अधिभार में जोड़ना
प्रकार: स्रोत-स्तरीय विराम।
प्रभावित भाषाएँ: C #, VB
प्रभावित न होने वाली भाषाएँ: F #
परिवर्तन से पहले एपीआई:
public class Foo
{
public static implicit operator int ();
}
परिवर्तन के बाद एपीआई:
public class Foo
{
public static implicit operator int ();
public static implicit operator float ();
}
नमूना ग्राहक कोड परिवर्तन से पहले काम कर रहा है और उसके बाद टूट गया है:
void Bar(int x);
void Bar(float x);
Bar(new Foo());
नोट: F # टूटा नहीं है, क्योंकि इसमें ओवरलोड ऑपरेटरों के लिए कोई भाषा स्तर का समर्थन नहीं है, न तो स्पष्ट और न ही अंतर्निहित - दोनों को सीधे op_Explicit
और op_Implicit
विधियों के रूप में बुलाया जाना है ।
नई आवृत्ति विधियों को जोड़ना
दयालु: स्रोत-स्तरीय शांत शब्दार्थ बदलते हैं।
प्रभावित भाषाएँ: C #, VB
प्रभावित न होने वाली भाषाएँ: F #
परिवर्तन से पहले एपीआई:
public class Foo
{
}
परिवर्तन के बाद एपीआई:
public class Foo
{
public void Bar();
}
नमूना ग्राहक कोड जो एक शांत शब्दार्थ परिवर्तन से ग्रस्त है:
public static class FooExtensions
{
public void Bar(this Foo foo);
}
new Foo().Bar();
नोट: F # टूटा नहीं है, क्योंकि इसमें भाषा स्तर का समर्थन नहीं है ExtensionMethodAttribute
और इसके लिए CLS एक्सटेंशन विधियों को स्टैटिक विधियों के रूप में बुलाया जाना आवश्यक है।