(এটি == নাল) সি # তে!


129

সি # 4 এ ঠিক করা একটি বাগের কারণে নিম্নলিখিত প্রোগ্রামটি মুদ্রণ করে true। (এটি লিনকিউপ্যাডে চেষ্টা করে দেখুন)

void Main() { new Derived(); }

class Base {
    public Base(Func<string> valueMaker) { Console.WriteLine(valueMaker()); }
}
class Derived : Base {
    string CheckNull() { return "Am I null? " + (this == null); }
    public Derived() : base(() => CheckNull()) { }
}

রিলিজ মোডে ভিএস ২০০৮ এ এটি একটি অবৈধপ্রগ্রাম এক্সসেপশন ছুড়ে দেয়। (ডিবাগ মোডে, এটি দুর্দান্ত কাজ করে)

ভিএস2010 বিটা 2-তে, এটি সংকলন করে না (আমি বিটা 1 চেষ্টা করিনি); আমি যে হার্ড উপায় শিখেছি

this == nullখাঁটি সি # তে তৈরি করার অন্য কোনও উপায় আছে কি ?


3
এটি সম্ভবত সি # 3.0 সংকলকটিতে একটি বাগ। এটি সি # ৪.০ এর মতো করে কাজ করে।
মেহরদাদ আফশারি

82
@ এসএলাক্স: বাগগুলির মধ্যে সমস্যা হ'ল আপনি আশা করতে পারেন যে এগুলি কোনও পর্যায়ে স্থির করা উচিত তাই তাদের "দরকারী" খুঁজে পাওয়া সম্ভবত বুদ্ধিমানের কাজ নয়।
অ্যান্থনি ডাব্লু জোন্স

6
ধন্যবাদ! লিনকিউপ্যাড সম্পর্কে জানতাম না। এটি জোশ!
কাঁটা ̈

8
কোন উপায়ে সঠিকভাবে এটি কার্যকর?
অ্যালেন রাইস

6
এই বাগটি কীভাবে কার্যকর ছিল?
ব্ল্যাকটাইগারএক্স

উত্তর:


73

এই পর্যবেক্ষণটি আজকের আগে আরও একটি প্রশ্নের স্ট্যাক ওভারফ্লোতে পোস্ট করা হয়েছে ।

মার্ক এর যে প্রশ্ন মহান উত্তর ইঙ্গিত করে যে বৈশিষ্ট (অধ্যায় 7.5.7) অনুযায়ী, আপনি সক্ষম অ্যাক্সেস করতে থাকা উচিত thisযে প্রেক্ষাপটে এবং # 3.0 কম্পাইলার একটি বাগ সি তা করার ক্ষমতা। সি # 4.0 সংকলক অনুমান অনুসারে সঠিক আচরণ করছে (এমনকি বিটা 1 তেও এটি একটি সংকলন সময় ত্রুটি):

Access 7.5.7 এই অ্যাক্সেস

একজন এই অ্যাক্সেস সংরক্ষিত শব্দ নিয়ে গঠিত this

এই-অ্যাক্সেস করুন:

this

একজন এই অ্যাক্সেস শুধুমাত্র অনুমতি দেওয়া হয় ব্লক একটি দৃষ্টান্ত কন্সট্রাকটর, একটি দৃষ্টান্ত পদ্ধতি, বা একটি দৃষ্টান্ত অ্যাকসেসর করুন।


2
আমি দেখতে পাচ্ছি না, কেন এই প্রশ্নে উপস্থাপিত কোডটিতে "এই" কীওয়ার্ডটির ব্যবহার অবৈধ। পদ্ধতি CheckNull একটি স্বাভাবিক উদাহরণস্বরূপ পদ্ধতি হল, nonstatic । এই পদ্ধতিতে "এটি" ব্যবহার করা 100% বৈধ এবং এমনকি এটি শূন্যের সাথে তুলনা করা বৈধ। ত্রুটিটি বেস ইআরআর লাইনে রয়েছে: এটি বেস কর্টারে প্যারামিটার হিসাবে দৃষ্টান্ত-সীমাবদ্ধ প্রতিনিধি পাস করার চেষ্টা। এটি সংকলকটির বাগ (সেম্যাটিক চেকগুলির একটি গর্ত): এটি সম্ভব হবে না। : base(CheckNull())চেকনুল স্ট্যাটিক না হলে আপনাকে লেখার অনুমতি নেই এবং একইভাবে কোনও উদাহরণ-বাঁধা ল্যাম্বডাকে ইনলাইন করতে সক্ষম হবেন না।
কোয়েটজলকোটল

4
@quetzalcoatl: thisমধ্যে CheckNullপদ্ধতি বৈধ। কি আইনি নয় অন্তর্নিহিত এই অ্যাক্সেস মধ্যে () => CheckNull()মূলত () => this.CheckNull(), যা বাইরে চলমান ব্লক একটি দৃষ্টান্ত কন্সট্রাকটর করুন। আমি সম্মত হই যে আমি যে অংশে উল্লেখ করেছি সে অংশটি মূলত thisকীওয়ার্ডের সিনট্যাক্টিক বৈধতার উপর দৃষ্টি নিবদ্ধ করে এবং সম্ভবত আরও একটি অংশ এই বিষয়টিকে আরও স্পষ্টভাবে সম্বোধন করে, তবে অনুমানের এই অংশটি থেকে ধারণাগতভাবে এক্সট্রোপোলেট করা সহজ।
মেহরদাদ আফশারি

2
দুঃখিত, আমি অসন্তুষ্ট। যদিও আমি জানি (এবং উপরের মন্তব্যে এটি লিখিত হয়েছে) এবং আপনি এটিও জানেন যে - আপনি আপনার (স্বীকৃত) উত্তরে সমস্যার আসল কারণটি উল্লেখ করেননি। উত্তরটি গৃহীত হয়েছে - সুতরাং সম্ভবত মনে হয় লেখক এটিকেও আঁকড়ে ধরেছেন। তবে আমি সন্দেহ করি যে সমস্ত পাঠক ল্যাম্বডাসের তুলনায় উজ্জ্বল এবং সাবলীল হয়ে উঠবেন যেমন প্রথম নজরে মানচিত্রের ল্যাম্বদা বনাম স্ট্যাটিক-ল্যাম্বদা এবং এটি ম্যাপ করে যে 'এটি' এবং নির্গত আইএল সমস্যা: এই কারণেই আমি আমার তিনটি সেন্ট যুক্ত করেছি।
তদুপরি

24

ডিবাগ মোড বাইনারিটির কাঁচা সংশ্লেষণ (কোনও অপ্টিমাইজেশনবিহীন প্রতিফলক) হ'ল:

private class Derived : Program.Base
{
    // Methods
    public Derived()
    {
        base..ctor(new Func<string>(Program.Derived.<.ctor>b__0));
        return;
    }

    [CompilerGenerated]
    private static string <.ctor>b__0()
    {
        string CS$1$0000;
        CS$1$0000 = CS$1$0000.CheckNull();
    Label_0009:
        return CS$1$0000;
    }

    private string CheckNull()
    {
        string CS$1$0000;
        CS$1$0000 = "Am I null? " + ((bool) (this == null));
    Label_0017:
        return CS$1$0000;
    }
}

সংকলক জেনারেটেড পদ্ধতিটি বোঝায় না; আপনি যদি আইএলটি (নীচে) দেখুন তবে এটি পদ্ধতিটিকে নাল স্ট্রিং (!) এ কল করছে।

   .locals init (
        [0] string CS$1$0000)
    L_0000: ldloc.0 
    L_0001: call instance string CompilerBug.Program/Derived::CheckNull()
    L_0006: stloc.0 
    L_0007: br.s L_0009
    L_0009: ldloc.0 
    L_000a: ret 

রিলিজ মোডে, স্থানীয় ভেরিয়েবলটি অপ্টিমাইজ করা হয়, সুতরাং এটি স্ট্যাকের উপর একটি অ-অযৌক্তিক ভেরিয়েবলটিকে ঠেলে দেওয়ার চেষ্টা করে।

    L_0000: ldloc.0 
    L_0001: call instance string CompilerBug.Program/Derived::CheckNull()
    L_0006: ret 

(রিফ্লেক্টরটিকে সি # তে পরিণত করার সময় ক্র্যাশ হয়)


সম্পাদনা : কেউ (এরিক লিপার্ট?) কম্পাইলারটি কেন প্রকাশ করে তা জানেন ldloc?


11

আমি যে ছিল! (এবং প্রমাণও পেয়েছি)

বিকল্প পাঠ


2
দেরি হয়ে গেছে, আমার কোডিং বন্ধ করা উচিত এমন একটি চিহ্ন ছিল :) আমাদের ডিএলআর স্টাফ আইআইআরসি দিয়ে হ্যাক করছিল।
লেলি

'এটি' যাই হোক না কেন তার জন্য একটি ডিবাগার ভিজ্যুয়ালাইজার (ডিবাগারডিসপ্লে) করুন এবং সেই নির্বোধকে যে শূন্য করে তুলুন? : ডি শুধু বলছেন '

10

এটি কোনও "বাগ" নয়। এটি আপনি টাইপ সিস্টেমটি আপত্তিজনক করছেন। আপনার কখনই thisকোনও নির্মাণকারীর মধ্যে কারও কাছে বর্তমান দৃষ্টান্ত ( ) -র একটি রেফারেন্স দেওয়ার কথা নয় ।

বেস ক্লাস কনস্ট্রাক্টরের মধ্যে ভার্চুয়াল পদ্ধতিতে কল করে আমি অনুরূপ "বাগ" তৈরি করতে পারি।

শুধু কারণ আপনার পারেন খারাপ কিছু করতে তার একটি অর্থ এই নয় বাগ যখন আপনি এটি অল্পে পেতে।


14
এটি একটি সংকলক বাগ। এটি অবৈধ আইএল উত্পন্ন করে। (আমার উত্তর পড়ুন)
এসএলএক্স

প্রসঙ্গটি স্থিতিশীল, সুতরাং আপনাকে সেই পর্যায়ে কোনও উদাহরণ পদ্ধতি রেফারেন্সের অনুমতি দেওয়া উচিত নয়।
লেপি

10
@ উইল: এটি একটি সংকলক বাগ। সংকলকটি সেই কোড স্নিপেটের জন্য বৈধ , যাচাইযোগ্য কোড উত্পন্ন করার বা একটি ত্রুটি বার্তা স্পিট আউট করার কথা। কোনও সংকলক যখন অনুমান অনুসারে আচরণ করে না তখন এটি বাগিচা হয়
মেহরদাদ আফশারি

2
@ উইল # 4: আমি কোডটি লেখার সময়, আমি এর অর্থ সম্পর্কে চিন্তা করিনি। আমি কেবল বুঝতে পেরেছিলাম যে যখন এটি ভিএস 2010-এ সংকলন বন্ধ করে দিয়েছে তখন এর কোনও অর্থ নেই। -
স্লাকস

3
যাইহোক, কনস্ট্রাক্টরে ভার্চুয়াল পদ্ধতি কলটি সম্পূর্ণ বৈধ অপারেশন। এটি কেবল প্রস্তাবিত নয়। এটি যৌক্তিক বিপর্যয়ের ফলস্বরূপ হতে পারে তবে কখনও তা হতে পারে না InvalidProgramException
মেহরদাদ আফশারি

3

আমি ভুল হতে পারি, তবে আমি নিশ্চিত যে যদি আপনার অবজেক্টটি এমন nullকোনও পরিস্থিতি হয় যেখানে কখনও thisপ্রযোজ্য না হয়।

উদাহরণস্বরূপ, আপনি কিভাবে কল করবেন CheckNull?

Derived derived = null;
Console.WriteLine(derived.CheckNull()); // this should throw a NullReferenceException

3
কনস্ট্রাক্টর আর্গুমেন্টে একটি ল্যাম্বডায়। পুরো কোড স্নিপেট পড়ুন। (এবং আপনি যদি আমাকে বিশ্বাস না করেন তবে এটি ব্যবহার করে দেখুন)
স্লাকস

আমি সম্মত হই যদিও সি ++ তে কীভাবে কোনও নির্মানকারীর মধ্যে কোনও জিনিসের রেফারেন্স ছিল না সে সম্পর্কে আমি খুব অল্প কিছু মনে রেখেছি এবং আমি ভাবছি যে এই পদ্ধতিতে কোনও কল ছিল কিনা তা পরীক্ষা করার জন্য (এই == নাল) পরিস্থিতি ব্যবহৃত হয় কিনা? "এটি" তে কোনও পয়েন্টার প্রকাশের আগে অবজেক্টের কনস্ট্রাক্টর থেকে তৈরি। যদিও, আমি সি # তে যতদূর জানি, এমন কোনও ক্ষেত্রেই এমন হওয়া উচিত নয় যেখানে "এই "টি সর্বদা বাতিল হবে, এমনকি নিষ্পত্তি বা চূড়ান্তকরণ পদ্ধতিতেও নয়।
jpierson

আমার অনুমান আমার বক্তব্যটি হ'ল একেবারেই ধারণাটি thisনাল হওয়ার সম্ভাবনা থেকে পারস্পরিক একচেটিয়া - কম্পিউটার প্রোগ্রামিংয়ের "কোজিটো, এর্গো সম" এর ধরণ। সুতরাং আপনার অভিব্যক্তিটি ব্যবহার করার this == nullএবং এটির সত্যিকারের ফিরে আসার ইচ্ছাটি আমাকে বিপথগামী হিসাবে আঘাত করে।
ড্যান টাও

অন্য কথায়: আমি আপনার কোড পড়েছি; আমি যা বলছি তা হ'ল আপনি প্রথমে কী অর্জন করার চেষ্টা করছেন তা আমি প্রশ্ন করি।
ড্যান তাও

এই কোডটি ত্রুটিটি সহজভাবে প্রদর্শন করে এবং যেমন আপনি দেখিয়েছেন, একেবারেই অকেজো। আসল দরকারী কোডটি দেখতে, আমার দ্বিতীয় উত্তরটি পড়ুন।
এসএলএক্স

-1

আপনি যা সন্ধান করছেন এটি এটি কিনা নিশ্চিত না

    public static T CheckForNull<T>(object primary, T Default)
    {
        try
        {
            if (primary != null && !(primary is DBNull))
                return (T)Convert.ChangeType(primary, typeof(T));
            else if (Default.GetType() == typeof(T))
                return Default;
        }
        catch (Exception e)
        {
            throw new Exception("C:CFN.1 - " + e.Message + "Unexpected object type of " + primary.GetType().ToString() + " instead of " + typeof(T).ToString());
        }
        return default(T);
    }

উদাহরণ: ইউজারআইডি = চেকফোর্ড নল (অনুরোধ.কুইয়ারিস্ট্রিং ["ইউজারআইডি"], 147);


13
আপনি প্রশ্নটি পুরোপুরি ভুল বুঝেছেন।
স্লাকস

1
আমি যতটা মূর্ত. ভেবেছিলাম যেভাবেই চেষ্টা করব।
স্কট এবং দেব দল
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.