সংগ্রহ <টি> বনাম তালিকা <টি> আপনার ইন্টারফেসে আপনার কী ব্যবহার করা উচিত?


162

কোডটি নীচের মত দেখাচ্ছে:

namespace Test
{
    public interface IMyClass
    {
        List<IMyClass> GetList();
    }

    public class MyClass : IMyClass
    {
        public List<IMyClass> GetList()
        {
            return new List<IMyClass>();
        }
    }
}

আমি কোড বিশ্লেষণ চালানোর সময় আমি নিম্নলিখিত প্রস্তাবটি পাই।

সতর্কতা 3 CA1002: মাইক্রোসফ্ট.ডিজাইন: সংগ্রহ, রিডঅনলি ক্লেশন বা কীডক্লিকেশন

আমি কীভাবে এটি ঠিক করব এবং এখানে ভাল অনুশীলন কী?

উত্তর:


234

কেন নয় তা প্রশ্নের "কেন" অংশটির উত্তর দেওয়ার জন্য List<T>, কারণগুলি হ'ল ভবিষ্যত-প্রুফিং এবং এপিআই সরলতা।

ভবিষ্যতে প্রুফিং

List<T>এটি সাবক্লাসিং করে সহজেই বর্ধমান করার জন্য ডিজাইন করা হয়নি; এটি অভ্যন্তরীণ বাস্তবায়নের জন্য দ্রুত হওয়ার জন্য ডিজাইন করা হয়েছে। আপনি লক্ষ্য করবেন যে এতে থাকা পদ্ধতিগুলি ভার্চুয়াল নয় এবং তাই ওভাররাইড করা যাবে না এবং এর Add/ Insert/ Removeক্রিয়াকলাপগুলিতে কোনও হুক নেই ।

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

সুতরাং যে কোনও শ্রেণিকে সহজেই সাবক্লাস করা যেতে পারে যেমন যেমন Collection<T>একটি ইন্টারফেস বা যেমন একটি ইন্টারফেস IList<T>, ICollection<T>বা IEnumerable<T>আপনি নিজের অভ্যন্তরীণ বাস্তবায়নটি আপনার প্রয়োজন মেটাতে আলাদা সংগ্রহের ধরণ হিসাবে পরিবর্তন করতে পারেন, ভোক্তাদের কোড ভঙ্গ না করে কারণ এটি এখনও ফেরত যেতে পারে যে ধরণের তারা আশা করছেন।

এপিআই সরলতা

List<T>যেমন দরকারী অপারেশনের অনেক রয়েছে BinarySearch, Sortইত্যাদি। তবে এটি যদি আপনি সংগ্রহ করছেন তবে এটি সম্ভবত আপনি গ্রাহকদের নয়, তালিকার শব্দার্থবিজ্ঞান নিয়ন্ত্রণ করছেন। সুতরাং আপনার শ্রেণীর অভ্যন্তরীণভাবে এই ক্রিয়াকলাপগুলির প্রয়োজন হতে পারে তবে আপনার শ্রেণীর গ্রাহকরা তাদের কল করতে (বা এমনকি বলা উচিত) খুব কম সম্ভাবনা রয়েছে।

যেমন, একটি সহজ সংগ্রহের ক্লাস বা ইন্টারফেসের প্রস্তাব দিয়ে, আপনি আপনার এপিআই এর ব্যবহারকারীরা যে সদস্য দেখেন তাদের সংখ্যা কমিয়ে দেয় এবং তাদের ব্যবহার সহজ করে তোলে।


1
এই প্রতিক্রিয়া মারা গেছে। বিষয়টিতে
ফেক্সকপ

7
আমি আপনার প্রথম পয়েন্টগুলি দেখতে পাচ্ছি, তবে আমি জানিনা যে আমি আপনার এপিআই এর সরলতার অংশে সম্মত কিনা।
বোরিস কলেনস

সংগ্রহ এবং তালিকার মধ্যে পার্থক্য কী তা সম্পর্কে stackoverflow.com/a/398988/2632991 এখানেও একটি সত্যিকারের ভাল পোস্ট।
এল ম্যাক

2
ব্লগস.এমএসডিএন / ফেক্সকপ / অর্চিভ / 2006 / 04 / 27/… -> মারা গেছে। আমাদের কি এর জন্য আরও নতুন তথ্য রয়েছে?
মাচাদো


50

আমি ব্যক্তিগতভাবে এটি একটি কংক্রিট সংগ্রহের চেয়ে ইন্টারফেস ফিরিয়ে দেওয়ার জন্য ঘোষণা করব। আপনি যদি সত্যিই তালিকার অ্যাক্সেস চান তবে ব্যবহার করুন IList<T>। অন্যথায়, বিবেচনা করুন ICollection<T>এবং IEnumerable<T>


1
আইলিস্ট তাহলে আইকোলিকেশন ইন্টারফেসটি বাড়িয়ে দেবে?
বোভিয়াম

8
@ জোন: আমি জানি এটি পুরানো, তবে আপনি কি ব্লজস.এমএসএনএন / বি / কেসিওয়ালিনা / আর্কাইভ / ২০০৫/০৯// / ২/ / 40৪০০.এএসপিএক্স- এ ক্রিজিসটফের বক্তব্য সম্পর্কে মন্তব্য করতে পারেন ? বিশেষত তাঁর মন্তব্য, We recommend using Collection<T>, ReadOnlyCollection<T>, or KeyedCollection<TKey,TItem> for outputs and properties and interfaces IEnumerable<T>, ICollection<T>, IList<T> for inputs. CA1002 Krzysztof এর মন্তব্যের সাথে বরাবর চলেছে বলে মনে হচ্ছে। ইন্টারফেসের পরিবর্তে কেন একটি কংক্রিট সংগ্রহের প্রস্তাব দেওয়া হবে এবং কেন ইনপুট / আউটপুটগুলির মধ্যে পার্থক্য হবে তা আমি ভাবতে পারি না।
নেলসন রোদারমেল

3
@Nelson: এটা বিরল যে আপনি চান প্রয়োজন একটি অপরিবর্তনীয় তালিকায় পাস কলারের, কিন্তু এটা যুক্তিসংগত এর আসতে তাই তারা জানে যে এটি স্পষ্টভাবে অপরিবর্তনীয় এর অন্যতম। অন্যান্য সংগ্রহ সম্পর্কে নিশ্চিত না যদিও। আরও বিস্তারিত জানলে ভাল লাগবে।
জন স্কিটি

2
এটি কোনও নির্দিষ্ট মামলার জন্য নয়। স্পষ্টতই সাধারণভাবে ReadOnlyCollection<T>কোনও ইনপুটটি বোঝায় না। একইভাবে, IList<T>যেমন একটি ইনপুট বলে, "আমার আইআরলিস্টে থাকা বাছাই করা () বা অন্য কোনও সদস্যের প্রয়োজন" যা আউটপুটটির পক্ষে কোনও অর্থ দেয় না। তবে আমি যা বোঝাতে চাইছিলাম তা কেন ICollection<T>ইনপুট Collection<T>হিসাবে এবং আউটপুট হিসাবে সুপারিশ করা হবে । আপনার প্রস্তাব অনুযায়ী আউটপুট হিসাবে ব্যবহার করবেন না কেন ICollection<T>?
নেলসন রডর্মেল

9
আমি ভাবছি এটি অসম্পূর্ণতা সঙ্গে করতে হবে। Collection<T>এবং ReadOnlyCollection<T>উভয়ই ICollection<T>(যেমন নেই IReadOnlyCollection<T>) থেকে প্রাপ্ত । আপনি যদি ইন্টারফেসটি ফিরিয়ে দেন তবে এটি কোনটি এবং এটি পরিবর্তন করা যায় কিনা তা স্পষ্ট নয়। যাইহোক, আপনার ইনপুট জন্য ধন্যবাদ। এটি আমার জন্য একটি ভাল স্যানিটি পরীক্ষা ছিল।
নেলসন রডর্মেল

3

আমি মনে করি না যে কেউ "কেন" অংশটি এখনও জবাব দিয়েছে ... তাই এখানে যায়। এর Collection<T>পরিবর্তে "কেন" আপনার "ব্যবহার করা উচিত List<T>কারণ আপনি যদি কোনওটিকে প্রকাশ করেন List<T>তবে যে কেউ আপনার বস্তুর অ্যাক্সেস পায় সে তালিকার আইটেমগুলিকে সংশোধন করতে পারে। যেখানে Collection<T>আপনি নিজের "অ্যাড", "সরান", ইত্যাদি পদ্ধতিগুলি ইঙ্গিত করছেন বলে ধারণা করা হচ্ছে।

আপনার সম্ভবত এটি নিয়ে মাথা ঘামানোর দরকার নেই, কারণ আপনি সম্ভবত নিজের জন্য ইন্টারফেস কোডিং করছেন (বা সম্ভবত কয়েকটি কলেজ)। এখানে অন্য একটি উদাহরণ রয়েছে যা বোধগম্য হতে পারে।

আপনার যদি সর্বজনীন অ্যারে থাকে তবে প্রাক্তন:

public int[] MyIntegers { get; }

আপনি ভাববেন যে কারণ কেবলমাত্র "গেট" অ্যাক্সেসর রয়েছে যে কেউ মানগুলির সাথে গণ্ডগোল করতে পারে না, তবে এটি সত্য নয়। যে কোনও ব্যক্তি ভিতরে মানগুলি এইভাবে পরিবর্তন করতে পারে:

someObject.MyIngegers[3] = 12345;

ব্যক্তিগতভাবে, আমি কেবল List<T>বেশিরভাগ ক্ষেত্রেই ব্যবহার করব । তবে আপনি যদি কোনও শ্রেণিবদ্ধ গ্রন্থাগার ডিজাইন করেন যা আপনি এলোমেলো বিকাশকারীদের দিতে চলেছেন, এবং আপনাকে অবজেক্টগুলির অবস্থার উপর নির্ভর করতে হবে ... তবে আপনি নিজের সংগ্রহ তৈরি করতে এবং সেখান থেকে এটি লক করে রাখতে চাইবেন: )


"আপনি যদি ক্লায়েন্ট কোডে <T> তালিকাটি ফিরিয়ে দেন তবে ক্লায়েন্ট কোড সংগ্রহটি পরিবর্তন করলে আপনি কখনই বিজ্ঞপ্তি পেতে সক্ষম হবেন না।" - এফএক্স সিওপি ... আরও দেখুন " এমএসডিএন.ইমক্রোসফটকম /en-us/library/0fss9skc.aspx " ... বাহ, দেখে মনে হচ্ছে আমি মোটেও বেস নই :)
টিমোথি খৌরি

বাহ - বছর পরে আমি দেখতে পাচ্ছি যে উপরের মন্তব্যে আমি যে লিঙ্কটি আটকেছিলাম তার শেষে একটি উদ্ধৃতি ছিল, সুতরাং এটি কার্যকর হয়নি ... msdn.microsoft.com/en-us/library/0fss9skc.aspx
তীমথিয় খৌরি

2

এটি বেশিরভাগ ক্ষেত্রে নিজের প্রয়োগগুলি বিমূর্ত করার বিষয়ে তালিকার অবজেক্টটি সরাসরি ম্যানিপুলেটেড করার পরিবর্তে প্রকাশের পরিবর্তে about

অন্যান্য বস্তুগুলিকে (বা লোকেরা) সরাসরি আপনার সামগ্রীর অবস্থা পরিবর্তন করতে দেওয়া ভাল অনুশীলন নয়। সম্পত্তি গেটার / সেটেটরগুলি ভাবেন।

সংগ্রহ -> সাধারণ সংগ্রহের
জন্য
পড়ুনআপনি সংগ্রহ -> যে সংকলনগুলির কেইডক্লিকেশনটি সংশোধন করা উচিত নয় -> আপনি যখন এর পরিবর্তে অভিধান চান তখন।

কীভাবে এটি ঠিক করবেন আপনি আপনার ক্লাসটি কী করতে চান এবং গেটলিস্ট () পদ্ধতির উদ্দেশ্য এর উপর নির্ভর করে। তুমি কি বিস্তারিত বলতে পারো?


1
তবে সংগ্রহ <টি> এবং কীডক্লিকেশন <,> কোনওটিই পঠনযোগ্য নয়।
নওফাল

@ নওফাল এবং আমি কোথায় বললাম যে এটি?
চক্রত

1
আপনি অন্য বস্তুগুলিকে (বা লোকেরা) সরাসরি আপনার অবজেক্টের স্থিতি পরিবর্তন করতে এবং 3 সংগ্রহের ধরণের তালিকা তৈরি করতে দেন না state ReadOnlyCollectionঅন্য দুজনকে বাদ দিয়ে তা মানা হয় না।
নওফাল

এটি "ভাল অনুশীলন" উল্লেখ করে। যথাযথ প্রসঙ্গ দয়া করে। ওপিতে সতর্কতাটি বুঝতে চায় বলে নীচে সেই তালিকাতে এই জাতীয় ধরণের প্রাথমিক প্রয়োজনটি সহজভাবে বর্ণনা করা হয়েছে state আমি তখন GetList()তাকে আরও সঠিকভাবে সহায়তা করতে সক্ষম হওয়ার উদ্দেশ্য সম্পর্কে তাকে জিজ্ঞাসা করি ।
চাকটি

1
ঠিক আছে আমি সে অংশটি বুঝতে পারি তবে তবুও যুক্তি অংশটি আমার মতে যথাযথ নয়। আপনি বলেছেন Collection<T>অভ্যন্তরীণ বাস্তবায়ন বিমূর্ত করতে সহায়তা করে এবং অভ্যন্তরীণ তালিকার সরাসরি কারচুপি রোধ করে। কিভাবে? Collection<T>নিছক একটি মোড়ক, একই ঘটনায় অপারেটিং পাস। এটি উত্তরাধিকারের জন্য গতিশীল সংগ্রহ, অন্য কিছু নয় (গ্রেগের উত্তর এখানে আরও প্রাসঙ্গিক)।
নওফাল

1

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


1

এটি জিজ্ঞাসা করার পরে অনেক দিন হয়ে গেলেও কিছু যুক্ত করার জন্য।

থেকে আপনার তালিকা টাইপ আহরিত যখন List<T>পরিবর্তে Collection<T>, আপনি সংরক্ষিত ভার্চুয়াল পদ্ধতি বাস্তবায়ন করতে পারবে না Collection<T>প্রয়োগ করা হয়। এর অর্থ হ'ল তালিকায় কোনও পরিবর্তন আনার ক্ষেত্রে আপনি প্রাপ্ত টাইপটি প্রতিক্রিয়া জানাতে পারবেন না। এর কারণ এটি List<T>ধরে নেওয়া হয় যে আপনি যখন আইটেমগুলি যুক্ত করেন বা সরিয়ে রাখেন তখন আপনি সচেতন হন। বিজ্ঞপ্তিগুলির প্রতিক্রিয়া জানাতে সক্ষম হওয়াই একটি ওভারহেড এবং তাই এটি সরবরাহ List<T>করে না।

যখন বাহ্যিক কোডের আপনার সংগ্রহে অ্যাক্সেস রয়েছে তখন আপনি যখন কোনও আইটেম যুক্ত বা অপসারণ করছেন তখন আপনি নিয়ন্ত্রণে রাখতে পারবেন না। সুতরাং Collection<T>আপনার তালিকাটি কখন সংশোধন করা হয়েছে তা জানার একটি উপায় সরবরাহ করে।


0

এরকম কিছু ফেরাতে আমি কোনও সমস্যা দেখছি না

this.InternalData.Filter(crteria).ToList();

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

তবে এটি নির্ভর করে আমি কী ধরণের গ্রাহক আশা করি - এটি যদি ডেটা গ্রিডের মতো কিছু হয় তবে আমি ফিরে যেতে পছন্দ করি IEnumerable<TItem> যা বেশিরভাগ ক্ষেত্রে আইটেমের অনুলিপি তালিকা হতে পারে :)


-1

ঠিক আছে সংগ্রহ শ্রেণিটি অন্যান্য সংগ্রহগুলির বাস্তব প্রয়োগের বিশদ এবং অন্যান্য বৈশিষ্ট্যগুলি গোপন করার জন্য কেবল একটি মোড়কের ক্লাস। আমি বিবেচনা করি এর সাথে সম্পত্তি সম্পর্কিত গোপন কোডিং প্যাটার্নটি অবজেক্ট ভিত্তিক ভাষাগুলির সাথে কিছু করার আছে।

আমি মনে করি আপনার এটি নিয়ে চিন্তা করা উচিত নয়, তবে আপনি যদি কোড বিশ্লেষণ সরঞ্জামটি সত্যিই খুশি করতে চান তবে কেবল নিম্নলিখিতটি করুন:

//using System.Collections.ObjectModel;

Collection<MyClass> myCollection = new Collection<MyClass>(myList);

1
দুঃখিত, এটি একটি টাইপ ছিল। আমি সংগ্রহ <মাই ক্লাস>। আমি সি # 4 এবং জেনেরিক কোভেরিয়েন্স বিটিডব্লিউতে আমার হাত পেতে সত্যিই অপেক্ষা করছি!
তামাস সিজনেজে

একটি মোড়ক মধ্যে মোড়ানো Collection<T>না যতটা আমি বুঝতে পেরেছি নিজেকে বা অন্তর্নিহিত সংগ্রহ না রক্ষা করে।
নওফাল

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