c# - GetType() झूठ बोल सकते हैं?




types (6)

निम्नलिखित प्रश्नों के आधार पर कुछ दिन पहले एसओ: गेट टाइप () और पॉलिमॉर्फिज्म और एरिक लिपर्ट के जवाब को पढ़ने में पूछा गया था, मैंने यह सोचना शुरू कर दिया कि GetType() को आभासी नहीं होने पर वास्तव में यह सुनिश्चित किया जाता है कि कोई वस्तु इसके Type बारे में झूठ नहीं बोल सकती है।

विशेष रूप से, एरिक का जवाब निम्नलिखित बताता है:

ढांचे के डिजाइनर एक अविश्वसनीय रूप से खतरनाक फीचर नहीं जोड़ रहे हैं जैसे ऑब्जेक्ट को अपने प्रकार के बारे में झूठ बोलने की इजाजत देना, इसे एक ही प्रकार के तीन अन्य तरीकों के साथ संगत बनाने के लिए।

अब सवाल यह है: क्या मैं ऐसी वस्तु बना सकता हूं जो इसके प्रकार के बारे में झूठ बोलता है बिना यह तुरंत स्पष्ट हो? मैं यहां गहराई से गलत हो सकता हूं और यदि मामला है तो मुझे स्पष्टीकरण पसंद आएगा, लेकिन निम्न कोड पर विचार करें:

public interface IFoo
{
    Type GetType();
}

और कहा इंटरफ़ेस के निम्नलिखित दो कार्यान्वयन:

public class BadFoo : IFoo
{
    Type IFoo.GetType()
    {
        return typeof(int);
    }
}

public class NiceFoo : IFoo
{
}

फिर यदि आप निम्न सरल कार्यक्रम चलाते हैं:

static void Main(string[] args)
{
    IFoo badFoo = new BadFoo();
    IFoo niceFoo = new NiceFoo();
    Console.WriteLine("BadFoo says he's a '{0}'", badFoo.GetType().ToString());
    Console.WriteLine("NiceFoo says he's a '{0}'", niceFoo.GetType().ToString());
    Console.ReadLine();
}

निश्चित रूप से पर्याप्त badFoo एक गलत Type उत्पादन करता है।

अब मुझे नहीं पता कि इस व्यवहार को " अविश्वसनीय रूप से खतरनाक फीचर " के रूप में वर्णित एरिक के आधार पर इसका कोई गंभीर प्रभाव है, लेकिन क्या यह पैटर्न एक विश्वसनीय खतरा बन सकता है?


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

आपने जो किया वह गेटटाइप को छायांकित करने जैसा है, इस तरह:

public class BadFoo
{
    public new Type GetType()
    {
        return typeof(int);
    }
}

इस वर्ग के साथ (और GetType () विधि के लिए एमएसडीएन से नमूना कोड का उपयोग करके) आप वास्तव में हो सकता है:

int n1 = 12;
BadFoo foo = new BadFoo();

Console.WriteLine("n1 and n2 are the same type: {0}",
                  Object.ReferenceEquals(n1.GetType(), foo.GetType())); 
// output: 
// n1 and n2 are the same type: True

तो, हाँ, आपने सफलतापूर्वक झूठ बोला है, है ना? खैर, हाँ और नहीं ... इस बात का उपयोग करें कि इसे शोषण के रूप में उपयोग करने से आपके BadFoo इंस्टेंस का उपयोग किसी विधि के लिए तर्क के रूप में किया जाएगा, जो object पदानुक्रम के लिए object या सामान्य आधार प्रकार की अपेक्षा करता है। कुछ इस तरह:

public void CheckIfInt(object ob)
{
    if(ob.GetType() == typeof(int))
    {
        Console.WriteLine("got an int! Initiate destruction of Universe!");
    }
    else
    {
        Console.WriteLine("not an int");
    }
}

लेकिन CheckIfInt(foo) प्रिंट "int नहीं"।

तो, मूल रूप से (आपके उदाहरण पर वापस), आप वास्तव में केवल अपने "झूठ बोलने वाले" कोड का उपयोग कर सकते हैं जो किसी ने आपके IFoo इंटरफ़ेस के खिलाफ लिखा था, जो इस तथ्य के बारे में बहुत स्पष्ट है कि इसमें "कस्टम" GetType() विधि है।

केवल अगर GetType () ऑब्जेक्ट पर वर्चुअल था, तो आप किसी "झूठ बोलने वाले" प्रकार को तैयार करने में सक्षम होंगे जिसका उपयोग किसी अन्य व्यक्ति द्वारा लिखे गए पुस्तकालयों में विनाश बनाने के लिए उपरोक्त CheckIfInt जैसी विधियों के साथ किया जा सकता है।


खैर, वास्तव में पहले से ही एक प्रकार है जो GetType में झूठ बोल सकता है: किसी भी शून्य प्रकार।

यह कोड :

int? x = 0; int y = 0;
Console.WriteLine(x.GetType() == y.GetType());

आउटपुट True

असल में, यह int? नहीं है int? कौन झूठ बोल रहा है, बस object लिए अंतर्निहित कास्ट int? बदल जाता है int? एक बॉक्सिंग int । लेकिन फिर भी आप int? नहीं बता सकते हैं int? GetType() साथ int से।


प्रकार के बारे में सुनिश्चित करने के दो तरीके हैं:

  1. उस प्रकार के प्रकार का उपयोग करें जिसे अधिभारित नहीं किया जा सकता है

    IFoo badFoo = new BadFoo();
    IFoo niceFoo = new NiceFoo();
    
    Console.WriteLine("BadFoo says he's a '{0}'", badFoo.GetType().ToString());
    Console.WriteLine("NiceFoo says he's a '{0}'", niceFoo.GetType().ToString());
    
    Console.WriteLine("BadFoo really is a '{0}'", typeof(BadFoo));
    Console.WriteLine("NiceFoo really is a '{0}'", typeof(NiceFoo));
    Console.ReadLine();
    
  2. उदाहरण को किसी object कास्ट करें और GetType() विधि को कॉल करें

    IFoo badFoo = new BadFoo();
    IFoo niceFoo = new NiceFoo();
    
    Console.WriteLine("BadFoo says he's a '{0}'", badFoo.GetType().ToString());
    Console.WriteLine("NiceFoo says he's a '{0}'", niceFoo.GetType().ToString());
    
    Console.WriteLine("BadFoo really is a '{0}'", ((object)badFoo).GetType());
    Console.WriteLine("NiceFoo really is a '{0}'", ((object)niceFoo).GetType());
    Console.ReadLine();
    

मुझे नहीं लगता कि यह होगा, चूंकि GetType को कॉल करने वाले प्रत्येक लाइब्रेरी कोड को वेरिएबल को 'ऑब्जेक्ट' या जेनेरिक टाइप 'टी' के रूप में घोषित किया जाएगा।

निम्नलिखित कोड:

    public static void Main(string[] args)
    {
        IFoo badFoo = new BadFoo();
        IFoo niceFoo = new NiceFoo();
        PrintObjectType("BadFoo", badFoo);
        PrintObjectType("NiceFoo", niceFoo);
        PrintGenericType("BadFoo", badFoo);
        PrintGenericType("NiceFoo", niceFoo);
    }

    public static void PrintObjectType(string actualName, object instance)
    {
        Console.WriteLine("Object {0} says he's a '{1}'", actualName, instance.GetType());
    }

    public static void PrintGenericType<T>(string actualName, T instance)
    {
        Console.WriteLine("Generic Type {0} says he's a '{1}'", actualName, instance.GetType());
    }

प्रिंट:

ऑब्जेक्ट BadFoo का कहना है कि वह एक 'TypeConcept.BadFoo' है

ऑब्जेक्ट नाइसफू का कहना है कि वह 'टाइप कॉन्सेप्ट.इसफू' है

सामान्य प्रकार BadFoo का कहना है कि वह एक 'TypeConcept.BadFoo' है

जेनेरिक टाइप नाइसफू का कहना है कि वह 'टाइप कॉन्सेप्ट.इसफू' है

इस तरह के कोड का एकमात्र समय खराब परिदृश्य के परिणामस्वरूप आपके कोड में होगा, जहां आप पैरामीटर प्रकार IFoo के रूप में घोषित करते हैं

    public static void Main(string[] args)
    {
        IFoo badFoo = new BadFoo();
        IFoo niceFoo = new NiceFoo();
        PrintIFoo("BadFoo", badFoo);
        PrintIFoo("NiceFoo", niceFoo);
    }

    public static void PrintIFoo(string actualName, IFoo instance)
    {
        Console.WriteLine("IFoo {0} says he's a '{1}'", actualName, instance.GetType());
    }

IFoo BadFoo का कहना है कि वह एक 'System.Int32' है

IFoo NiceFoo का कहना है कि वह एक 'TypeConcept.NiceFoo' है


सबसे बुरी बात यह हो सकती है कि जहां तक ​​मैं कह सकता हूं कि निर्दोष प्रोग्रामर भ्रामक है जो जहरीले वर्ग का उपयोग करते हैं, उदाहरण के लिए:

Type type = myInstance.GetType();
string fullName = type.FullName;
string output;
if (fullName.Contains(".Web"))
{
    output = "this is webby";
}
else if (fullName.Contains(".Customer"))
{
    output = "this is customer related class";
}
else
{
    output = "unknown class";
}

यदि myInstance इंस्टेंस एक वर्ग का उदाहरण है जैसे कि आप प्रश्न में वर्णन करते हैं, तो इसे अभी अज्ञात प्रकार के रूप में माना जाएगा।

तो मेरा जवाब नहीं है, यहां कोई वास्तविक खतरा नहीं दिख रहा है।


object.GetType बीच एक अंतर है। IFoo.GetType object.GetType और IFoo.GetTypeGetType को संकलित समय पर ज्ञात वस्तुओं पर नहीं कहा जाता है, इंटरफ़ेस पर नहीं। आपके उदाहरण में, आउटपुट badFoo.GetType साथ यह badFoo.GetType की उम्मीद है, क्योंकि आप विधि को अधिभारित करते हैं। केवल एक चीज है, कि अन्य प्रोग्रामर इस व्यवहार से भ्रमित हो सकते हैं।

लेकिन अगर आप typeof() उपयोग करते हैं तो यह आउटपुट होगा कि टाइप समान है, और आप typeof() ओवरराइट नहीं कर सकते हैं।

इसके अलावा प्रोग्रामर संकलन समय पर देख सकते हैं, जिस विधि को वह GetType आमंत्रित करता है।

तो आपके प्रश्न के लिए: यह पैटर्न एक विश्वसनीय खतरा उत्पन्न नहीं कर सकता है, लेकिन यह कोडिंग की सबसे अच्छी शैली भी नहीं है।





types