কখন IList ব্যবহার করবেন এবং কখন তালিকা ব্যবহার করবেন


179

আমি জানি যে আইলিস্ট হ'ল ইন্টারফেস এবং তালিকাটি হ'ল কংক্রিটের ধরণ তবে এখনও প্রতিটিটি কখন ব্যবহার করতে হবে তা আমি জানি না। আমি এখন যা করছি তা হল যদি আমি ইন্টারফেসটি ব্যবহার করে বাছাই বা ফাইন্ডএল পদ্ধতিগুলির প্রয়োজন না হয়। আমি কি সঠিক? ইন্টারফেস বা কংক্রিটের ধরণটি কখন ব্যবহার করবেন তা স্থির করার আরও ভাল উপায় আছে?


1
যে কেউ এখনও ভাবছি হয়, তাহলে আমি সেরা উত্তর এখানে খুঁজে পাও: stackoverflow.com/questions/400135/listt-or-ilistt
Crismogram

উত্তর:


174

আমি দুটি নিয়ম অনুসরণ করি:

  • কাজ করবে এমন সর্বাধিক প্রাথমিক ধরণটি গ্রহণ করুন
  • আপনার ব্যবহারকারীর প্রয়োজন হবে সবচেয়ে ধনী টাইপ করুন

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

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


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

11
আমি 2 টি নিয়মের সাথে একমত নই ... এই ক্ষেত্রে IList (আরও ভাল ধারণাযোগ্য) ফিরে আসার সময় আমি বেশিরভাগ আদিম ধরণের এবং বিশেষ ব্যবহার করব এবং আপনার অভ্যন্তরের তালিকার সাথে আপনার কাজ করা উচিত। তারপরে আপনার যখন "অ্যাড" বা "বাছাই" দরকার হয় তখন আরও প্রয়োজনে সংগ্রহ ব্যবহার করুন তবে তালিকাটি ব্যবহার করুন। সুতরাং আমার কঠোর নিয়মটি হ'ল: সর্বদা আইইনুয়ামের সাথে শুরু করুন এবং আপনার যদি আরও বেশি প্রয়োজন হয় তবে প্রসারিত করুন ...
এথেম

2
আপনার সুবিধার জন্য, "দুটি নিয়ম" এর একটি নাম রয়েছে: দৃust়তা নীতি (ওরফে পোস্টেলের আইন)
ইজোনকক্সজ

সর্বাধিক প্রাথমিক টাইপটি বা সবচেয়ে ধনীতম টাইপটি ফিরিয়ে আনতে হবে কিনা সে সম্পর্কে কারও বিতর্কের যে দিকটি রয়েছে তা বিবেচনা করার মতো বিষয় হ'ল খুব সরলীকৃত ইন্টারফেসটি ফিরিয়ে দেওয়ার সময়, গ্রাহক কোডটি প্রায়শই সময় করতে পারে - যদিও সর্বদা নয় - চিত্রটির if...elseজন্য isকীওয়ার্ড সহ একটি চেইন ব্যবহার করুন এটির জন্য আরও বেশি ধরণের টাইপ করুন এবং এটিতে ingালাই করা এবং যাইহোক এটি ব্যবহার করে শেষ করুন। তাই আপনি যদি না অগত্যা লুকান কিছু মৌলিক ইন্টারফেস ব্যবহার করে, পরিবর্তে শুধু আড়াল এর নিশ্চিত। তবে এটিকে আরও শক্ত করে তোলা গ্রাহক কোডের লেখক তারা কীভাবে এটি ব্যবহার করছেন সে সম্পর্কে দ্বিগুণ চিন্তা করতে পারে।
Panzercrisis

6
আমি পয়েন্ট # 2 সম্পর্কে খুব দৃ strongly়ভাবে একমত নই, বিশেষত যদি এটি কোনও পরিষেবা / এপিআই সীমানায় থাকে। সংশোধনযোগ্য সংগ্রহের রিটার্নিং ছাপ যে সংগ্রহগুলি "লাইভ" এবং মত পদ্ধতি আহ্বান করা হয় দিতে পারেন Add()এবং Remove()মাত্র সংগ্রহে পরলোক প্রভাব থাকে। কেবল পঠনযোগ্য ইন্টারফেসের মতো ফিরিয়ে আনা IEnumerableপ্রায়শই ডেটা-পুনরুদ্ধার পদ্ধতিতে যাওয়ার উপায়। আপনার ভোক্তা এটি প্রয়োজন হিসাবে আরও ধনী আকারে প্রজেক্ট করতে পারেন।
এসটিডাব্লু

56

মাইক্রোসফ্ট গাইডলাইনগুলি FxCop দ্বারা চেক করা হিসাবে পাবলিক এপিআইতে <T> তালিকার ব্যবহার নিরুত্সাহিত করে - IList <T> পছন্দ করে prefer

প্রসঙ্গত, আমি এখন প্রায়শই IList <T> হিসাবে এক-মাত্রিক অ্যারেগুলি ঘোষণা করি, যার অর্থ আমি ধারাবাহিকভাবে IList <T> ব্যবহার করতে পারি Ar উদাহরণ স্বরূপ:

public interface IMyApi
{
    IList<int> GetReadOnlyValues();
}

public class MyApiImplementation : IMyApi
{
    public IList<int> GetReadOnlyValues()
    {
        List<int> myList = new List<int>();
        ... populate list
        return myList.AsReadOnly();
    }
}
public class MyMockApiImplementationForUnitTests : IMyApi
{
    public IList<int> GetReadOnlyValues()
    {
        IList<int> testValues = new int[] { 1, 2, 3 };
        return testValues;
    }
}

3
আমি এই ব্যাখ্যা / উদাহরণটি সবচেয়ে পছন্দ করি!
জোনএইচ

28

এখানে একটি গুরুত্বপূর্ণ বিষয় রয়েছে যা লোকেরা সবসময় উপেক্ষা করে বলে মনে করে:

আপনি কোনও কিছুতে একটি সরল অ্যারে পাস করতে পারেন যা কোনও IList<T>প্যারামিটার গ্রহণ করে এবং তারপরে আপনি কল করতে পারেন IList.Add()এবং রানটাইম ব্যতিক্রম পাবেন:

Unhandled Exception: System.NotSupportedException: Collection was of a fixed size.

উদাহরণস্বরূপ, নিম্নলিখিত কোডটি বিবেচনা করুন:

private void test(IList<int> list)
{
    list.Add(1);
}

আপনি যদি নিম্নলিখিতটিকে কল করেন তবে আপনি রানটাইম ব্যতিক্রম পাবেন:

int[] array = new int[0];
test(array);

এটি ঘটেছিল কারণ প্লেইন অ্যারে ব্যবহার IList<T>করে লিসকভ প্রতিস্থাপন নীতি লঙ্ঘন করা হয়।

এই কারণে, আপনি কল দিলে আপনি IList<T>.Add()একটি List<T>পরিবর্তে একটি প্রয়োজন বিবেচনা করতে চাইতে পারেন IList<T>


প্রতিটি ইন্টারফেসের ক্ষেত্রে এটি তুচ্ছভাবে সত্য। আপনি যদি নিজের যুক্তিটি অনুসরণ করতে চান তবে আপনি কখনও কোনও ইন্টারফেসটি কখনও ব্যবহার না করার পক্ষে যুক্তি দিতে পারেন, কারণ এটির কিছু বাস্তবায়ন নষ্ট হতে পারে। আপনি, অপরপক্ষে, পরামর্শ ওপি কর্তৃক প্রদত্ত পছন্দ বিবেচনা List<T>উপর IList<T>, এছাড়াও আপনি কেন সচেতন হতে হবে IList<T>বাঞ্ছনীয়। (উদাহরণস্বরূপ ব্লগস.এমএসএনএন.মাইক্রোসফট.কেসিওয়ালিনা/2005/09/26/… )
মিশা

3
@ মিচাওয়েডেনম্যান আপনার উত্তরটি যখন আপনি কল করছেন তখন সুনির্দিষ্ট IList<T>.Add()। আমি বলছি না যে আপনার ব্যবহার করা উচিত নয়IList<T> - আমি কেবল একটি সম্ভাব্য সমস্যাটি দেখিয়ে দিচ্ছি। (আমি ব্যবহারের প্রবণতা IEnumerable<T>বা IReadOnlyList<T>বা IReadOnlyCollection<T>পক্ষপাত করা IList<T>যদি আমি করতে পারেন।)
ম্যাথু ওয়াটসন

24

আমি প্যারামিটার নেওয়ার জন্য লির পরামর্শের সাথে একমত হব, কিন্তু ফিরে আসছি না।

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

অবশ্যই এটি কেবলমাত্র বাহ্যিকভাবে দৃশ্যমান (যেমন জনসাধারণের পদ্ধতি) প্রয়োগ করা উচিত methods আমি ব্যক্তিগতভাবে এমনকি অভ্যন্তরীণ কোডে ইন্টারফেসও ব্যবহার করি, তবে আপনি যদি সমস্ত ব্রেক কোড নিজে পরিবর্তন করতে সক্ষম হন তবে এটি কঠোরভাবে প্রয়োজনীয় নয়।


21

অপরিহার্য
আপনার চেষ্টা করা উচিত এবং আপনার উদ্দেশ্য অনুসারে সর্বনিম্ন নির্দিষ্ট ধরণের ব্যবহার করা উচিত।
IEnumerableতুলনায় কম নির্দিষ্ট IList
আপনি IEnumerableযখন কোনও সংগ্রহের আইটেমগুলি লুপ করতে চান তখন আপনি ব্যবহার করুন ।

আইলিস্ট
IList প্রয়োগসমূহ IEnumerable। আপনার সংগ্রহের সূচী দ্বারা অ্যাক্সেসের প্রয়োজন হলে, উপাদানগুলি যোগ করুন এবং মুছুন ইত্যাদি আপনার
ব্যবহার করা উচিত IList...

তালিকা
List প্রয়োগ IList


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

9

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

সংগ্রহের জন্য আপনার লক্ষ্য করা উচিত যেখানে সম্ভব সম্ভব ব্যবহার করা উচিত। এটি সর্বাধিক নমনীয়তা দেয় তবে সর্বদা উপযুক্ত নয়।


1
সর্বনিম্ন বেস প্রকারের সম্ভাব্যটিকে গ্রহণ করা সর্বদা সেরা । প্রত্যাবর্তন অন্যরকম গল্প। কোন বিকল্পগুলি কার্যকর হতে পারে তা চয়ন করুন। সুতরাং আপনি কি মনে করেন আপনার ক্লায়েন্ট সূচিযুক্ত অ্যাক্সেস ব্যবহার করতে পারে? ToList()আপনার প্রত্যাবর্তিত IEnumerable<T>যা ইতিমধ্যে একটি তালিকা ছিল সেগুলি এগুলি থেকে সরিয়ে রাখুন এবং IList<T>পরিবর্তে একটি ফেরত দিন । এখন, ক্লায়েন্টরা আপনি প্রচেষ্টা ব্যতীত যা সরবরাহ করতে পারেন তার থেকে উপকৃত হতে পারে।
টিমো

5

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


4

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

উদাহরণস্বরূপ, ধরা যাক আপনার একটি Personক্লাস এবং একটি Groupক্লাস রয়েছে। একটি Groupউদাহরণে অনেক লোক রয়েছে, সুতরাং এখানে একটি তালিকা অর্থপূর্ণ হবে। যখন আমি তালিকার অবজেক্টটিকে ডিক্লেয়ার করব তখন আমি এটি Groupব্যবহার করব IList<Person>এবং এটি হিসাবে একটি ইনস্ট্যান্ট করব List

public class Group {
  private IList<Person> people;

  public Group() {
    this.people = new List<Person>();
  }
}

এবং, আপনার যদি এমনকি সমস্ত কিছু প্রয়োজন IListনা হয় তবে সর্বদা ব্যবহার করতে পারেন IEnumerable। আধুনিক সংকলক এবং প্রসেসর সহ, আমি ভাবি না যে সত্যিই কোনও গতির পার্থক্য রয়েছে, সুতরাং এটি কেবল স্টাইলের বিষয়।


3
কেন এটি প্রথম স্থানে কেবল একটি তালিকা তৈরি করে না? আমি এখনও বুঝতে পারছি না যে আপনি কেন এটির আইলিস্ট তৈরি করে বোনাস পান তবে কনস্ট্রাক্টারে আপনি এটিকে একটি তালিকা তৈরি করেন <>
chobo2

আমি সম্মত হই, আপনি যদি স্পষ্টভাবে একটি তালিকা <টি> অবজেক্ট তৈরি করছেন তবে আপনি ইন্টারফেসের সুবিধাটি হারাবেন?
The_Butcher

4

আপনি সর্বাধিক সাধারণ ব্যবহারযোগ্য প্রকারটি ব্যবহারের ক্ষেত্রে আরও ভাল, এক্ষেত্রে আইলিস্ট বা আরও ভাল আইএনউবারেবল ইন্টারফেস, যাতে আপনি পরবর্তী সময়ে কার্যকরভাবে পরিবর্তনটি পরিবর্তন করতে পারেন।

যাইহোক, .NET 2.0 এ, একটি বিরক্তিকর জিনিস রয়েছে - IList এর একটি বাছাইকরণ পদ্ধতি নেই () । পরিবর্তে সরবরাহিত অ্যাডাপ্টার ব্যবহার করতে পারেন:

ArrayList.Adapter(list).Sort()

2

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

যদি তালিকাটি একমাত্র বাস্তবায়ন হয় যা আপনি কখনও নির্দিষ্ট সংগ্রহের জন্য ব্যবহার করেন তবে এটিকে কংক্রিট তালিকা বাস্তবায়ন হিসাবে নির্দ্বিধায় ঘোষণা করুন।


1

যে পরিস্থিতিতে আমি সাধারণত আসি, আমি খুব কমই সরাসরি আইলিস্ট ব্যবহার করি।

সাধারণত আমি এটি কেবল কোনও পদ্ধতির আর্গুমেন্ট হিসাবে ব্যবহার করি

void ProcessArrayData(IList almostAnyTypeOfArray)
{
    // Do some stuff with the IList array
}

এটি আমাকে .NET ফ্রেমওয়ার্কের প্রায় কোনও অ্যারে জেনেরিক প্রক্রিয়াজাতকরণের অনুমতি দেবে, যদি না এটি আইএনমিটারেবল এবং আইলিস্ট না ব্যবহার করে, যা কখনও কখনও ঘটে থাকে।

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


1

অ্যালিস্ট অবজেক্ট আপনাকে একটি তালিকা তৈরি করতে, এতে জিনিস যুক্ত করতে, এটি সরিয়ে ফেলার, আপডেট করার, এটির সূচক এবং ইত্যাদির অনুমতি দেয় whenever তালিকাটি যখনই আপনি কেবল জেনেরিক তালিকা চান যেখানে আপনি এটিতে অবজেক্টের ধরণ উল্লেখ করেন এবং তা এটিই হয়।

অন্যদিকে আইলিস্ট হ'ল একটি ইন্টারফেস। মূলত, আপনি যদি নিজের ধরণের তালিকা তৈরি করতে চান তবে বুকলিস্ট নামে একটি তালিকা শ্রেণি বলুন, তবে আপনি ইন্টারফেসটি আপনার নতুন ক্লাসে প্রাথমিক পদ্ধতি এবং কাঠামো দেওয়ার জন্য ব্যবহার করতে পারেন। IList হল যখন আপনি নিজের তৈরি করতে চান, বিশেষ উপ-শ্রেণি যা তালিকাকে কার্যকর করে।

আর একটি পার্থক্য হ'ল: আইলিস্ট হ'ল একটি ইন্টারফেস এবং তা ইনস্ট্যান্ট করা যাবে না। তালিকাটি একটি শ্রেণি এবং তাত্ক্ষণিকভাবে চালু করা যেতে পারে। এর অর্থ:

IList<string> MyList = new IList<string>();

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