সেরা অনুশীলনগুলি কেবল পঠনযোগ্য অবজেক্টকে ফিরে আসবে


11

আমার # সি-তে ওওপি সম্পর্কে "সেরা অনুশীলন" প্রশ্ন রয়েছে (তবে এটি সাজানো-ই সমস্ত ভাষার ক্ষেত্রে প্রযোজ্য)।

জনসাধারণের কাছে প্রকাশিত হওয়া অবজেক্টের সাথে লাইব্রেরি ক্লাস থাকার কথা বিবেচনা করুন, সম্পত্তি অ্যাকসেসরের মাধ্যমে বলুন, তবে আমরা জনসাধারণ (এই গ্রন্থাগার বর্গ ব্যবহারকারী লোকেরা) এটি পরিবর্তন করতে চাই না।

class A
{
    // Note: List is just example, I am interested in objects in general.
    private List<string> _items = new List<string>() { "hello" }

    public List<string> Items
    {
        get
        {
            // Option A (not read-only), can be modified from outside:
            return _items;

            // Option B (sort-of read-only):
            return new List<string>( _items );

            // Option C, must change return type to ReadOnlyCollection<string>
            return new ReadOnlyCollection<string>( _items );
        }
    }
}

স্পষ্টতই সর্বোত্তম পন্থা হ'ল "অপশন সি", তবে খুব অল্প কিছু অবজেক্টের রিডইনলি ভেরিয়েন্ট থাকে (এবং অবশ্যই কোনও ব্যবহারকারী-সংজ্ঞায়িত শ্রেণীর এটি নেই)।

আপনি যদি ক্লাস এ এর ​​ব্যবহারকারী হন, আপনি কি পরিবর্তনের আশা করতেন?

List<string> someList = ( new A() ).Items;

মূল (এ) অবজেক্টে প্রচার করুন? অথবা কোনও ক্লোনটি প্রদান করা ঠিক আছে যে এটি মন্তব্য / ডকুমেন্টেশনে তাই লেখা হয়েছিল? আমি মনে করি যে এই ক্লোন পদ্ধতির ফলে বেশ কঠিন-ট্র্যাক-ত্রুটি হতে পারে to

আমি মনে করি যে সি ++ তে আমরা কনস্ট অবজেক্টগুলি ফিরিয়ে দিতে পারতাম এবং আপনি কেবল তার উপর কনস্ট হিসাবে চিহ্নিত পদ্ধতিগুলিকে কল করতে পারেন। আমার ধারণা সি # তে তেমন কোনও বৈশিষ্ট্য / প্যাটার্ন নেই? যদি না হয় তবে তারা কেন এটি অন্তর্ভুক্ত করবে না? আমি বিশ্বাস করি এটাকে কনস্টেনস নির্ভুলতা বলা হয়।

তবে তারপরে আবার আমার মূল প্রশ্নটি "আপনি কী আশা করবেন" বা অপশন এ বনাম বি কীভাবে পরিচালনা করবেন তা নিয়ে is


2
.NET 4.5: ব্লগস.এমএসএনএন / বি / বিসিএলটিম / আর্কাইভ / ২০১২ / १२ / ১৮ / এর জন্য নতুন অপরিবর্তনীয় সংগ্রহগুলির এই পূর্বরূপ সম্পর্কে এই নিবন্ধটি দেখুন। আপনি ইতিমধ্যে সেগুলি নুগেটের মাধ্যমে পেতে পারেন।
ক্রিস্টফ ক্লেস

উত্তর:


10

@ জেসির উত্তর ছাড়াও, যা সংগ্রহের জন্য সেরা সমাধান: সাধারণ ধারণাটি হ'ল আপনার পাবলিক ইন্টারফেসটিকে এমনভাবে ডিজাইন করা যাতে এটি কেবল ফিরে আসে না does

  • মান প্রকার (যেমন int, ডাবল, কাঠামো)

  • অপরিবর্তনীয় অবজেক্টস ("স্ট্রিং" এর মতো, বা ব্যবহারকারী সংজ্ঞায়িত ক্লাসগুলি যা কেবলমাত্র আপনার পাঠ্য A-এর মতো কেবল পঠন পদ্ধতি সরবরাহ করে)

  • (কেবলমাত্র যদি আপনার প্রয়োজন হয়): অবজেক্ট অনুলিপিগুলি যেমন আপনার "বিকল্প বি" প্রদর্শন করে

IEnumerable<immutable_type_here> নিজে থেকে পরিবর্তনযোগ্য, সুতরাং এটি কেবল উপরের একটি বিশেষ ক্ষেত্রে।


19

এছাড়াও লক্ষ করুন যে আপনার ইন্টারফেসগুলিতে প্রোগ্রামিং হওয়া উচিত এবং বৃহত্তর আপনি কী সেই সম্পত্তি থেকে ফিরে আসতে চান তা একটি IEnumerable<string>। এ List<string>হ'ল নো-এর কিছুটা কারণ এটি সাধারণত পরিবর্তনযোগ্য এবং আমি এতদূর যেতে পারি যে ReadOnlyCollection<string>একজন বাস্তবায়নকারী হিসাবে ICollection<string>মনে হয় যে এটি লিসকভ সাবস্টিটিউশন নীতি লঙ্ঘন করে।


6
+1, একটি ব্যবহার করা IEnumerable<string>হ'ল এখানে কী চায়।
ডক ব্রাউন 15

2
নেট .৪.৫ এ আপনিও ব্যবহার করতে পারেন IReadOnlyList<T>
সুইভ

3
অন্যান্য আগ্রহী পক্ষের জন্য নোট। সম্পত্তি অ্যাক্সেসরের কথা বিবেচনা করার সময়: আপনি যদি কেবল তালিকার <স্ট্রিং> এর পরিবর্তে আইনিংরেবল <স্ট্রিং> ফিরিয়ে দেন _ তালিকা করে (+ অন্তর্ভুক্ত castালাইকে আইনিউমেবল) তবে এই তালিকাটি আবার তালিকা <স্ট্রিং> এ ফেলে দেওয়া যেতে পারে এবং পরিবর্তনগুলি হবে এবং পরিবর্তনগুলি হবে মূল বস্তুতে প্রচার করুন। আপনি নতুন তালিকা <স্ট্রিং> (_লিস্ট) (+ পরবর্তী জড়িত কাস্ট আইইনিউমারেবল) করতে পারেন যা অভ্যন্তরীণ তালিকাকে সুরক্ষিত করবে। এ সম্পর্কে আরও এখানে পাওয়া যাবে: স্ট্যাকওভারফ্লো.com
নেভারস্টপলিয়ারিং

1
কোনও সংগ্রহের যে কোনও প্রাপক যাকে সূচকের মাধ্যমে এটি অ্যাক্সেস করতে হবে তার প্রয়োজন কি আরও ভাল হয় যে তথ্যটি এমন কোনও প্রকারে অনুলিপি করার জন্য প্রস্তুত থাকতে হবে, বা সংগ্রহটি ফেরত দেওয়া কোডটি কোনও ফর্মের মধ্যে সরবরাহ করা প্রয়োজন এটির চেয়ে আরও ভাল that সূচক দ্বারা অ্যাক্সেসযোগ্য? সরবরাহকারী যদি এমন আকারে না থাকে যা সূচকের মাধ্যমে অ্যাক্সেসের সুবিধা দেয় না, তবে আমি বিবেচনা করব যে প্রাপককে তাদের নিজস্ব অপ্রয়োজনীয় অনুলিপি তৈরির প্রয়োজন থেকে মুক্ত করার মান সরবরাহকারীকে সরবরাহ করা থেকে মুক্ত করার মানকে অতিক্রম করবে একটি এলোমেলোভাবে অ্যাক্সেস ফর্ম (যেমন কেবলমাত্র পঠনযোগ্য IList<T>)
সুপারক্যাট

2
আইনিউমারেবলের বিষয়ে একটি জিনিস আমি পছন্দ করি না তা হ'ল আপনি কখনই জানেন না যে এটি কোনও কর্টিন হিসাবে চালিত হয় বা এটি কেবল একটি ডেটা অবজেক্ট whether যদি এটি কোনও কর্টিন হিসাবে চালিত হয় তবে এটি সূক্ষ্ম বাগের ফলস্বরূপ হতে পারে তাই এটি কখনও কখনও জেনে রাখা ভাল। এই কারণেই আমি রিডঅনলি সংগ্রহ বা আইআরইডলিলিস্ট ইত্যাদি পছন্দ করি
স্টিভ ভার্মিউলেন

3

আমি কিছুক্ষণ আগে একইরকম সমস্যার মুখোমুখি হয়েছিলাম এবং নীচে আমার সমাধানটি ছিল, তবে আপনি যদি লাইব্রেরিটিও নিয়ন্ত্রণ করেন তবে এটি সত্যিই কাজ করবে:


আপনার ক্লাস দিয়ে শুরু করুন A

public class A
{
    private int _n;
    public int N
    {
        get { return _n; }
        set { _n = value; }
    }
}

তারপরে এগুলি থেকে কেবলমাত্র বৈশিষ্ট্যের অংশ (এবং যে কোনও পড়ার পদ্ধতি) পাওয়া যায় এবং এটি প্রয়োগ করে এটিকে দিয়ে একটি ইন্টারফেস পান

public interface IReadOnlyA
{
    public int N { get; }
}
public class A : IReadOnlyA
{
    private int _n;
    public int N
    {
        get { return _n; }
        set { _n = value; }
    }
}

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


2
এটির সাথে সমস্যা হ'ল এটি পরিবর্তনীয় সংস্করণে ফেরত দেওয়া সম্ভব। এবং এর এলএসপি এর ভায়োলিয়েশন, বেস ক্লাসের (এই ক্ষেত্রে ইন্টারফেসের) পদ্ধতির মাধ্যমে পর্যবেক্ষণযোগ্য ব্যাকস স্টেটগুলি উপক্লাস থেকে নতুন পদ্ধতিতে পরিবর্তন করা যেতে পারে। তবে এটি কমপক্ষে অভিপ্রায়টি কার্যকর করে না, এমনকি যদি এটি প্রয়োগ করে না।
ব্যবহারকারী470365

1

যারা এই প্রশ্ন খুঁজে বের করে এবং এখনও উত্তর আগ্রহী যে কেউ জন্য - এখন অন্য কোনো বিকল্প যা প্রকাশক হয় ImmutableArray<T>। এগুলি এমন কয়েকটি বিষয় যা আমি মনে করি এটি এর চেয়ে ভাল IEnumerable<T>বা ReadOnlyCollection<T>:

  • এটি পরিষ্কারভাবে জানিয়েছে যে এটি অপরিবর্তনীয় (অভিব্যক্তিপূর্ণ এপিআই)
  • এটি পরিষ্কারভাবে জানিয়েছে যে সংগ্রহটি ইতিমধ্যে গঠিত হয়েছে (অন্য কথায় এটি অলসভাবে শুরু করা হয়নি এবং এটি একাধিকবার পুনরাবৃত্তি করা ঠিক আছে)
  • যদি আইটেমগুলির গণনাটি জানা থাকে, তবে এটি এমন জ্ঞানগ্রেডটি লুকায় IEnumerable<T>না
  • যেহেতু ক্লায়েন্ট জানেন না কী বাস্তবায়ন হয় IEnumerableবা IReadOnlyCollectতিনি ধরে নিতে পারেন না যে এটি কখনই বদলে যায় না (অন্য কথায় কোনও গ্যারান্টি নেই যে কোনও সংগ্রহের আইটেমগুলি পরিবর্তিত হয়নি এবং সেই সংস্থার রেফারেন্স অপরিবর্তিত থাকে)

এছাড়াও যদি এপি-র সংগ্রহের পরিবর্তনের বিষয়ে ক্লায়েন্টকে অবহিত করা দরকার হয় তবে আমি আলাদা সদস্য হিসাবে কোনও ইভেন্ট প্রকাশ করব।

মনে রাখবেন যে আমি IEnumerable<T>এটি সাধারণভাবে খারাপ বলছি না । সংগ্রহটি আর্গুমেন্ট হিসাবে পাস করার সময় বা অলসভাবে প্রাথমিক সংগ্রহ সংগ্রহ করার সময় আমি এখনও এটি ব্যবহার করতাম (এই বিশেষ ক্ষেত্রে এটি আইটেমের গণনা গোপন করাতে বুদ্ধিমান কারণ এটি এখনও জানা যায়নি)।

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