আমি কীভাবে অপরিবর্তনীয় ক্ষেত্রগুলিতে সেটারগুলি পরিচালনা করব?


25

আমার দুটি readonly intক্ষেত্র সহ একটি ক্লাস আছে । এগুলি সম্পত্তি হিসাবে প্রকাশিত হয়:

public class Thing
{
    private readonly int _foo, _bar;

    /// <summary> I AM IMMUTABLE. </summary>
    public Thing(int foo, int bar)
    {
        _foo = foo;
        _bar = bar;
    }

    public int Foo { get { return _foo; } set { } }

    public int Bar { get { return _bar; } set { } }
}

তবে এর অর্থ এই যে নিচেরটি পুরোপুরি আইনী কোড:

Thing iThoughtThisWasMutable = new Thing(1, 42);

iThoughtThisWasMutable.Foo = 99;  // <-- Poor, mistaken developer.
                                  //     He surely has bugs now. :-(

যে বাগগুলি কাজ করবে তা ধরে নেওয়ার ফলে যে বাগগুলি আসবে তা নিশ্চয়ই ছদ্মবেশী। অবশ্যই, ভুল বিকাশকারীদের ডক্সগুলি পড়া উচিত ছিল। তবে এটি এই সত্যটি পরিবর্তন করে না যে কোনও সংকলন-বা রান-টাইম ত্রুটি তাকে সমস্যার বিষয়ে সতর্ক করেছিল।

Thingক্লাসটি কীভাবে পরিবর্তন করা উচিত যাতে ডেভস উপরোক্ত ভুল করার সম্ভাবনা কম করে?

ব্যতিক্রম ছুঁড়ে? কোনও সম্পত্তির পরিবর্তে একটি গেটর পদ্ধতি ব্যবহার করবেন?



1
ধন্যবাদ, @ জাগ্রত এই পোস্টটি (প্রশ্ন এবং উত্তর উভয়ই) ইন্টারফেসের সাথে কথা বলে মনে হচ্ছে, যেমন রাজধানী I তে Interfaces। আমি নিশ্চিত না যে আমি যা করছি
kdbanman

6
@ জাগান, এটি ভয়ঙ্কর পরামর্শ। ইন্টারফেসগুলি সার্বজনীনভাবে অপরিবর্তনীয় ভিও / ডিটিওগুলিকে পরিবেশন করার দুর্দান্ত উপায় সরবরাহ করে যা পরীক্ষা করা এখনও সহজ।
ডেভিড আরনো

4
@ জাগ্রত, আমি করেছি এবং প্রশ্নটির কোনও অর্থ নেই কারণ ওপি মনে করে যে ইন্টারফেসগুলি অপরিবর্তনীয়তা নষ্ট করে দেবে, যা বাজে কথা।
ডেভিড আরনো

1
@ প্রশ্ন, এই প্রশ্নটি ডিটিওর জন্য ইন্টারফেস ঘোষণার বিষয়ে ছিল। শীর্ষে ভোট দেওয়া উত্তরটি ছিল যে ইন্টারফেসগুলি ক্ষতিকারক হবে না, তবে সম্ভবত অপ্রয়োজনীয়।
পল ড্রপার

উত্তর:


107

কেন এই কোড আইনী? যদি এটি কিছু না
করে set { }তবে বাইরে বেরোন।
আপনি কেবলমাত্র পঠনযোগ্য সরকারী সম্পত্তিকে এইভাবে সংজ্ঞায়িত করেন:

public int Foo { get { return _foo; } }

3
আমি মনে করি না যে এটি কোনও কারণে আইনী, তবে এটি পুরোপুরি কার্যকর বলে মনে হচ্ছে! সঠিক ধন্যবাদ.
kdbanman

1
@ কেডব্যানম্যান এর আইডিই এক পর্যায়ে আপনাকে দেখেছে এমন কিছুটির সাথে সম্ভবত এটি করার কিছু আছে - সম্ভবত স্বয়ংক্রিয়ভাবে সমাপ্তি।
Panzercrisis

2
@kdbanman; কী আইনী নয় (সি # 5 অবধি) হ'ল public int Foo { get; }(কেবলমাত্র একজন গেটারের সাথে অটো-সম্পত্তি) তবে public int Foo { get; private set; }এটি।
লরেন্ট এলএ রিজ্জা

@ লরেন্টলারিজা, আপনি আমার স্মৃতি জাগিয়েছেন। আমার কনফিউশনটি ঠিক এখান থেকেই এসেছে।
kdbanman

45

সি # 5 এর সাথে এবং এর আগে, আমরা একজন গেটরের মাধ্যমে উন্মুক্ত ক্ষেত্রগুলির জন্য দুটি বিকল্পের মুখোমুখি হয়েছিলাম:

  1. কেবল পঠনযোগ্য ব্যাকিং ভেরিয়েবল তৈরি করুন এবং ম্যানুয়াল গেটারের মাধ্যমে এটি ফিরিয়ে দিন। এই বিকল্পটি সুরক্ষিত ( readonlyঅপরিবর্তনশীলতা ধ্বংস করার জন্য একটি অবশ্যই স্পষ্টভাবে মুছে ফেলতে হবে It এটি প্রচুর বয়লার-প্লেট কোড তৈরি করেছে।
  2. একটি ব্যক্তিগত সেটার সহ একটি অটো-সম্পত্তি ব্যবহার করুন। এটি সহজ কোড তৈরি করে তবে দুর্ঘটনাক্রমে অপরিবর্তনীয়তা ভঙ্গ করা সহজ।

যদিও সি # 6 সহ (ভিএস ২০১৫ এ উপলব্ধ, যা গতকাল প্রকাশিত হয়েছিল), আমরা এখন উভয় বিশ্বের সেরা: পঠনযোগ্য অটো বৈশিষ্ট্যগুলি পেয়েছি। এটি আমাদের ওপেনের ক্লাসটিকে সহজ করার অনুমতি দেয়:

public class Thing
{
    /// <summary> I AM IMMUTABLE. </summary>
    public Thing(int foo, int bar)
    {
        Foo = foo;
        Bar = bar;
    }

    public int Foo { get; }
    public int Bar { get; }
}

Foo = fooএবং Bar = barলাইনগুলি কেবল কনস্ট্রাক্টারে বৈধ (যা কেবলমাত্র শক্তিশালী পঠনযোগ্য প্রয়োজনীয়তা অর্জন করে) এবং ব্যাকিং ফিল্ডটি সুস্পষ্টভাবে সংজ্ঞায়িত না করে (যা সহজ কোডটি অর্জন করে) পরিবর্তিত হয়।


2
এবং প্রাথমিক নির্মাতারা নির্মাণকারীর সিনট্যাকটিক ওভারহেড থেকে মুক্তি পেয়ে এটিকে আরও সহজ করতে পারেন।
সেবাস্তিয়ান রেডল

3
@ সেবাস্তিয়ানআরডেল দুঃখের বিষয়, প্রাথমিক নির্মাতাদের চূড়ান্ত সি # 6 প্রকাশ থেকে সরানো হয়েছে
ড্যান লায়ন্স

1
@ ড্যানলায়ন্স ড্যাম, আমি আমাদের কোডবেস জুড়ে এটি ব্যবহারের অপেক্ষায় ছিলাম।
সেবাস্তিয়ান রেডল

12

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

public class Thing
{
    public Thing(int foo, int bar)
    {
        Foo = foo;
        Bar = bar;
    }

    public int Foo { get; private set; }

    public int Bar { get; private set; }
}

1
" public int Foo { get; private set; }" এই শ্রেণিটি আর পরিবর্তনযোগ্য নয় কারণ এটি নিজেই পরিবর্তন করতে পারে। ধন্যবাদ যদিও!
kdbanman

4
বর্ণিত শ্রেণিটি পরিবর্তনযোগ্য, কারণ এটি নিজের পরিবর্তিত হয় না।
ডেভিড আরনো

1
আমার আসল ক্লাসটি আমি যে এমডাব্লুই দিয়েছিলাম তা আরও জটিল । আমি আসল অপরিবর্তনীয়তার পরে , থ্রেড সুরক্ষা এবং শ্রেণি-অভ্যন্তরীণ গ্যারান্টি দিয়ে পূর্ণ।
kdbanman

4
@ কেডব্যানম্যান, এবং আপনার বক্তব্যটি কি? যদি আপনার শ্রেণিটি নির্মাণের সময় কেবলমাত্র বেসরকারী সেটটারগুলিকেই লেখেন, তবে এটি "সত্যিকারের অপরিবর্তনীয়তা" প্রয়োগ করেছে। readonlyশব্দ মাত্র একটি poka-জোয়াল, অর্থাত্ এটা বর্গ ভবিষ্যতে immutablity ভঙ্গ বিরুদ্ধে গার্ড; এটি অপরিবর্তনীয়তা অর্জন করার প্রয়োজন হয় না যদিও।
ডেভিড আরনো

3
আকর্ষণীয় শব্দটি, আমাকে এটি গুগল করতে হয়েছিল - পোকা-জোয়াল একটি জাপানি শব্দ যা "ভুল-প্রুফিং" এর অর্থ। তুমি ঠিক বলছো! আমি ঠিক তাই করছি।
kdbanman

6

দুটি সমাধান।

সরল:

অপরিবর্তনীয় পঠনযোগ্য বস্তুর জন্য ডেভিড দ্বারা উল্লিখিত সেটারগুলি অন্তর্ভুক্ত করবেন না।

বিকল্পভাবে:

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

pseudocode

public class Thing
{

{readonly vars}

    public Thing(int foo, int bar)
    {
        _foo = foo;
        _bar = bar;
    }

    public Thing withFoo(int foo) {
        return new Thing(foo, getBar());
    }

    public Thing withBar(int bar) {
        return new Thing(getFoo(), bar)
    }

    etc...
}

পাবলিক স্ট্যাটিক কারখানা

public class Thing
{

{readonly vars}

    private Thing(int foo, int bar)
    {
        _foo = foo;
        _bar = bar;
    }

    public static with(int foo, int bar) {
        return new Thing(foo, bar)
    }

    public Thing withFoo(int foo) {
        return new Thing(foo, getBar());
    }

    public Thing withBar(int bar) {
        return new Thing(getFoo(), bar)
    }

    etc...
}

2
সেট এক্সওয়াইজেড কারখানার পদ্ধতিগুলির জন্য ভয়ঙ্কর নাম, এক্সওয়াইজেড বা এর মতো বিবেচনা করুন।
বেন ভয়েগট

ধন্যবাদ, আপনার সহায়ক মন্তব্য প্রতিফলিত করতে আমার উত্তর আপডেট। :-)
ম্যাট স্মিথিজ

প্রশ্নটি সেটার পদ্ধতি নয়, সম্পত্তি সেটার সম্পর্কে বিশেষত জিজ্ঞাসা করছিল ।
ব্যবহারকারী 253751

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