পঠনযোগ্য ক্ষেত্রের জন্য অপরিষ্কার পদ্ধতি বলা হয়


84

আমি ভিজ্যুয়াল স্টুডিও 2010 + পুনঃ ভাগ করা ব্যবহার করছি এবং এটি নিম্নলিখিত কোডে একটি সতর্কতা দেখায়:

if (rect.Contains(point))
{
    ...
}

rectএকটি readonly Rectangleক্ষেত্র, এবং পুনরায় ভাগ করা এই সতর্কতা আমাকে দেখায়:

"মান প্রকারের পঠনক্ষেত্রের ক্ষেত্রের জন্য অপবিত্র পদ্ধতিটি কল করা হয়।"

অপরিষ্কার পদ্ধতিগুলি কী এবং কেন আমাকে এই সতর্কতা দেখানো হচ্ছে?


উত্তর:


96

প্রথমে, জোন, মাইকেল এবং জ্যারেডের উত্তরগুলি মূলত সঠিক তবে আমার কাছে আরও কয়েকটি জিনিস যুক্ত করতে চাই।

"অপরিষ্কার" পদ্ধতি বলতে কী বোঝায়?

খাঁটি পদ্ধতিগুলি বৈশিষ্ট্যযুক্ত করা আরও সহজ। একটি "খাঁটি" পদ্ধতিতে নিম্নলিখিত বৈশিষ্ট্য রয়েছে:

  • এর আউটপুট সম্পূর্ণভাবে তার ইনপুট দ্বারা নির্ধারিত হয়; দিনের ফলাফল বা আপনার হার্ড ডিস্কের বিটগুলির মতো বাহ্যিকতার উপর এর আউটপুট নির্ভর করে না। এর আউটপুট তার ইতিহাসের উপর নির্ভর করে না; প্রদত্ত যুক্তি দিয়ে দু'বার পদ্ধতিটি কল করা একই ফলাফল দেওয়া উচিত।
  • একটি খাঁটি পদ্ধতি তার চারপাশের বিশ্বে কোনও পর্যবেক্ষণযোগ্য মিউটেশন তৈরি করে না। একটি খাঁটি পদ্ধতি দক্ষতার জন্য প্রাইভেট স্টেটকে পরিবর্তিত করতে পারে, তবে একটি খাঁটি পদ্ধতি বলে না, তার যুক্তির ক্ষেত্রটি পরিবর্তন করে।

উদাহরণস্বরূপ, Math.Cosএকটি খাঁটি পদ্ধতি। এর আউটপুট কেবল তার ইনপুট উপর নির্ভর করে, এবং ইনপুট কল দ্বারা পরিবর্তন হয় না।

অপরিষ্কার পদ্ধতি এমন একটি পদ্ধতি যা খাঁটি নয়।

নাপাক পদ্ধতিতে পাঠযোগ্য মাত্রায় পাস করার কিছু বিপদ কী কী?

মনে আছে দুটি আছে। প্রথমটি হ'ল জন, মাইকেল এবং জারেড দ্বারা চিহ্নিত একটি এবং এটিই রিশার্পার আপনাকে সতর্ক করছে। আপনি যখন স্ট্রাক্টে কোনও পদ্ধতিতে কল করেন, আমরা পদ্ধতিটি চলকটি পরিবর্তিত করতে চাইলে প্রেরণকারী হিসাবে চলকটির জন্য একটি রেফারেন্সটি সর্বদা প্রেরণ করি।

তাহলে আপনি যদি ভেরিয়েবলের পরিবর্তে কোনও মানকে এই জাতীয় পদ্ধতিটি কল করেন? সেক্ষেত্রে আমরা একটি অস্থায়ী পরিবর্তনশীল করব, এর মধ্যে মানটি অনুলিপি করব এবং ভেরিয়েবলের একটি রেফারেন্স দিন।

একটি পঠনযোগ্য ভেরিয়েবলকে একটি মান হিসাবে বিবেচনা করা হয়, কারণ এটি কনস্ট্রাক্টরের বাইরে রূপান্তরিত হতে পারে না। সুতরাং আমরা ভেরিয়েবলটিকে অন্য ভেরিয়েবলে অনুলিপি করছি, এবং যখন আপনি ভেরিয়েবলটি পরিবর্তন করতে চান তখন অপরিষ্কার পদ্ধতিটি অনুলিপিটি সম্ভবত অনুলিপি করে চলেছে।

এটি রিসিভার হিসাবে কেবল পাঠ্য কাঠামো পাস করার বিপদ । এমন একটি কাঠামো পেরিয়ে যাওয়ার ঝুঁকিও রয়েছে যার মধ্যে কেবল পাঠযোগ্য ক্ষেত্র রয়েছে। একটি কাঠামো যাতে কেবল পাঠ্য ক্ষেত্র থাকে সেগুলি একটি প্রচলিত অনুশীলন, তবে এটি প্রয়োজনীয়ভাবে একটি চেক লিখতে থাকে যে টাইপ সিস্টেমে নগদ অর্থের তহবিল নেই; নির্দিষ্ট ভেরিয়েবলের "কেবলমাত্র পঠনযোগ্য নেস" স্টোরেজের মালিক দ্বারা নির্ধারিত হয়। রেফারেন্স টাইপের একটি উদাহরণ তার নিজস্ব স্টোরেজ "মালিকানাধীন" করে তবে মান ধরণের উদাহরণটি দেয় না!

struct S
{
  private readonly int x;
  public S(int x) { this.x = x; }
  public void Badness(ref S s)
  {
    Console.WriteLine(this.x);   
    s = new S(this.x + 1);
    // This should be the same, right?
    Console.WriteLine(this.x);   
  }
}

কেউ ভাবেন যে this.xএটি পরিবর্তন হচ্ছে না কারণ এক্স একটি পাঠ্য ক্ষেত্র এবং Badnessকোনও নির্মাণকারক নয়। তবে ...

S s = new S(1);
s.Badness(ref s);

... এর মিথ্যাচার স্পষ্টভাবে প্রদর্শন করে। thisএবং sএকই ভেরিয়েবলটি উল্লেখ করুন এবং সেই পরিবর্তনশীলটি কেবল পঠনযোগ্য নয়!


ন্যায্যতা উত্সাহিত হয়েছে , তবে দয়া করে এই কোডটি বিবেচনা করুন: টুয়েন্ট অশুচি struct Id { private readonly int _id; public Id(int id) { _id = id; } public int ToInt() => _id; } কেন ?
বোস্কিথেব্রেইন

@ বসকিটিক্রাবেইন: আপনার প্রশ্নটি কি আসলে "রিশার্পার এটিকে অশুদ্ধ মনে করে?" যদি এটি আপনার প্রশ্ন হয় তবে আর # এ কাজ করে এমন কাউকে সন্ধান করুন এবং তাদের জিজ্ঞাসা করুন!
এরিক লিপার্ট

4
পদ্ধতিটি অকার্যকর এবং ব্যতীত অন্য কিছু না করলেও রিশার্পার এই সতর্কতা দেবে return। তার উপর ভিত্তি করে, আমি অনুমান করছি যে একমাত্র মানদণ্ডটি পদ্ধতিটির [Pure]বৈশিষ্ট্য আছে কি না is
bornfromanegg

আমি এই বিবৃতিটি পেয়েছি "আমরা সর্বদা সেই পরিবর্তনশীলটির একটি রেফারেন্স পাস করি যা প্রাপক" আমার কাছে কিছুটা বিভ্রান্তিকর। পিও এর ক্ষেত্রে, 'ভেরিয়েবল' কী বোঝায়? আমি এটা অনুমান করা হবে rect। আমরা কি বলছি যে একটি অনুলিপি পদ্ধতিতে rectপাস হয়েছে Contains?
xtu

51

একটি অপরিষ্কার পদ্ধতি হ'ল যা মানটি যেমন রেখেছিল তেমন গ্যারান্টিযুক্ত নয়।

.NET 4-এ আপনি [Pure]খাঁটি বলে ঘোষণা করার জন্য পদ্ধতি এবং প্রকারগুলি সজ্জিত করতে পারেন এবং আর # এটি নোটিশ নেবে। দুর্ভাগ্যক্রমে, আপনি এটিকে অন্য কারও সদস্যের সাথে প্রয়োগ করতে পারবেন না এবং আপনি আর # কে বোঝাতে পারবেন না যে কোনও প্রকার / সদস্য একটি নেট নেট project.৩ প্রকল্পে খাঁটি, যতক্ষণ না আমি অবগত রয়েছি। (এটি সর্বদা নোদা টাইমে আমাকে কামড়ায় ))

ধারণা যে আপনি একটি পদ্ধতি একটি পরিবর্তনশীল আহ্বান করছি, তাহলে mutates, কিন্তু আপনি একটি শুধুমাত্র পাঠযোগ্য ক্ষেত্রের উপর সেটিতে কল, তাহলে সম্ভবত সেটি হল না করছেন কি আপনি চান, তাই আর # এই সম্পর্কে আপনাকে সতর্ক করবে। উদাহরণ স্বরূপ:

public struct Nasty
{
    public int value;

    public void SetValue()
    {
        value = 10;
    }
}

class Test
{
    static readonly Nasty first;
    static Nasty second;

    static void Main()
    {
        first.SetValue();
        second.SetValue();
        Console.WriteLine(first.value);  // 0
        Console.WriteLine(second.value); // 10
    }
}

প্রকৃত যে পদ্ধতিটি খাঁটি ছিল সেভাবে যদি সেইভাবে ঘোষণা করা হয় তবে এটি সত্যিই দরকারী সতর্কতা হবে। দুর্ভাগ্যক্রমে তারা না, তাই অনেক মিথ্যা ইতিবাচক রয়েছে :(


সুতরাং এর অর্থ এই যে কোনও অপরিষ্কার পদ্ধতি এটিতে প্রদত্ত মিউটেবল ভ্যালুটিটাইপের অন্তর্নিহিত ক্ষেত্রগুলিকে পরিবর্তন করতে পারে?
এসিডিক

@ এসিডিক: আর্গুমেন্টের মান নয় - এমনকী একটি অপরিষ্কার পদ্ধতিও এটি করতে পারে - তবে আপনি যে মানটিকে কল করেন তা । (আমার উদাহরণটি দেখুন, যেখানে পদ্ধতিটির কোনও
পরামিতিও নেই

4
আপনি এর JetBrains.Annotations.PureAttributeপরিবর্তে ব্যবহার করতে পারেন System.Diagnostics.Contracts.PureAttribute, রিশার্পার কোড বিশ্লেষণের জন্য এগুলির একই অর্থ এবং 3.5 নেট 3.5,। নেট 4 বা সিলভারলাইটে সমানভাবে কাজ করা উচিত। এক্সএমএল ফাইলগুলি ব্যবহার করে আপনার নিজের মালিকানাধীন অ্যাসেমস্লিগুলি আপনি বাহ্যিকভাবেও এনারোটেট করতে পারেন (রিসার্পার বিন পাথের এক্সটার্নালঅ্যানোটেশন ডিরেক্টরিটি দেখুন) এটি সত্যিই বেশ কার্যকর হতে পারে!
জুলিয়েন লেবোসকাইন

4
@ জুলিয়েনবেসকোইন: বিশেষত একটি ওপেন সোর্স প্রকল্পের জন্য - আমি সরঞ্জাম-নির্দিষ্ট টীকা যুক্ত করা শুরু করতে সত্যিই অনীহা বোধ করব। একটি বিকল্প হিসাবে সম্পর্কে জেনে রাখা ভাল, কিন্তু ...
জন স্কিটি

4
আসলে আমি পেয়েছি যে System.Diagnostics.Contracts.PureAttributeআর # 8.2-এ এই সতর্কতাটি দমন করতে পারে নি, যখন JetBrains.Annotations.PureAttributeকরেছিল। দুটি বৈশিষ্ট্যের আলাদা আলাদা বিবরণও রয়েছে: চুক্তির Pureবৈশিষ্ট্যগুলি বোঝায় "ফলাফল কেবলমাত্র পরামিতিগুলির উপর নির্ভর করে", যখন জেটব্রেইনস Pureবোঝায় যে ফলাফলটি গণনা করার জন্য অবজেক্টের অবস্থা বাদ দিয়ে "দৃশ্যমান স্থিতির পরিবর্তন ঘটায় না"। (তবে এখনও এই চুক্তিগুলির Pureএকই প্রভাব না থাকা চুক্তিগুলি সম্ভবত একটি বাগ।)
ওয়ারম্বো

15

সংক্ষিপ্ত উত্তরটি হ'ল এটি একটি মিথ্যা ইতিবাচক এবং আপনি সতর্কতাটিকে নিরাপদে উপেক্ষা করতে পারেন।

দীর্ঘতর উত্তরটি হ'ল কেবলমাত্র পঠনযোগ্য মান ধরণের অ্যাক্সেসই এর একটি অনুলিপি তৈরি করে, যাতে কোনও পদ্ধতির দ্বারা তৈরি মানটির কোনও পরিবর্তন কেবল অনুলিপিটিকেই প্রভাবিত করে। রিসার্পার বুঝতে পারে না যে Containsএটি একটি খাঁটি পদ্ধতি (যার অর্থ এর কোনও পার্শ্ব প্রতিক্রিয়া নেই)। এরিক লিপার্ট এখানে এ সম্পর্কে কথা বলেছেন: রিডোনলি স্ট্রাক্টসকে মিউটেশন করা


4
সম্পূর্ণ বোঝা না হওয়া পর্যন্ত দয়া করে এই সতর্কতাটিকে কখনই উপেক্ষা করবেন না !!! এটি আপনার সুরক্ষিত করতে পারে তার একটি ভাল উদাহরণ হ'ল এই নির্মাণটি: private readonly SpinLock _spinLock = new SpinLock();- এই জাতীয় লক সম্পূর্ণরূপে অকেজো হয়ে যায় (যেহেতু কেবলমাত্র পাঠ্যরূপে পরিবর্তনকারী অন-দ্য ফ্লাইট অনুলিপিটি তৈরি করার জন্য প্রতিবার এন্ট্র পদ্ধতিটি কল করা হয়)
জানু

11

দেখে মনে হচ্ছে রিশ্যাপারার বিশ্বাস করেন যে পদ্ধতিটি মানটিকে Containsপরিবর্তন করতে rectপারে। কারণ rectএকটি readonly structসি # সংকলক পদ্ধতির readonlyক্ষেত্রটিকে পরিবর্তিত করতে বাধা দিতে মানটির রক্ষণাত্মক অনুলিপিগুলি তৈরি করে । মূলত চূড়ান্ত কোডটি এর মতো দেখাচ্ছে

Rectangle temp = rect;
if (temp.Contains(point)) {
  ...
}

রিশার্পার আপনাকে এখানে সতর্ক করছে যে এটি এমনভাবে Containsপরিবর্তন rectকরতে পারে যা অবিলম্বে হারিয়ে যেতে পারে কারণ এটি অস্থায়ীভাবে ঘটেছিল।


সুতরাং এটি পদ্ধতিতে সঞ্চালিত কোনও যুক্তিকে প্রভাবিত করবে না, কেবল এটির মানটিকে পরিবর্তিত করা থেকে বিরত রাখবে যে, ডান?
এসিডিক

5

অপরিষ্কার পদ্ধতি এমন একটি পদ্ধতি যা এর পার্শ্ব প্রতিক্রিয়া হতে পারে। এই ক্ষেত্রে, রিশার্পার মনে হয় এটি পরিবর্তন হতে পারে rect। এটি সম্ভবত না কিন্তু প্রমাণের চেইনটি ভেঙে গেছে।

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