সি # কেন সূচকযুক্ত বৈশিষ্ট্যগুলি প্রয়োগ করে না?


83

আমি জানি, আমি জানি ... এ জাতীয় প্রশ্নের উত্তর এরিক লিপার্টের উত্তর সাধারণত "" কারণ এটি ডিজাইনিং, বাস্তবায়ন, পরীক্ষা এবং ডকুমেন্টিংয়ের ব্যয়বহুল ছিল না "।

তবে তবুও, আমি আরও ভাল ব্যাখ্যা চাই ... আমি নতুন ব্লগ # 4 নতুন বৈশিষ্ট্যগুলি সম্পর্কে এই ব্লগ পোস্টটি পড়ছিলাম এবং সিওএম ইন্টারপ সম্পর্কে বিভাগে, নীচের অংশটি আমার দৃষ্টি আকর্ষণ করেছে:

যাইহোক, এই কোডটি আরও একটি নতুন বৈশিষ্ট্য ব্যবহার করে: সূচিযুক্ত বৈশিষ্ট্য (সীমার পরে square বর্গাকার বন্ধনীগুলির দিকে ঘনিষ্ঠভাবে নজর দিন)) তবে এই বৈশিষ্ট্যটি কেবল সিওএম ইন্টারপের জন্য উপলভ্য; আপনি সি # 4.0 এ আপনার নিজস্ব ইনডেক্স বৈশিষ্ট্য তৈরি করতে পারবেন না

ঠিক আছে কিন্তু কেন ? আমি ইতিমধ্যে জানতাম এবং আফসোস করেছি যে সি # তে সূচিযুক্ত বৈশিষ্ট্য তৈরি করা সম্ভব ছিল না, তবে এই বাক্যটি আমাকে এ সম্পর্কে আবার ভাবতে বাধ্য করে। আমি এটি বাস্তবায়নের বেশ কয়েকটি ভাল কারণ দেখতে পাচ্ছি:

  • সিএলআর এটি সমর্থন করে (উদাহরণস্বরূপ, PropertyInfo.GetValueএকটি indexপ্যারামিটার রয়েছে), সুতরাং এটি দুঃখের বিষয় আমরা সি # তে এর সুবিধা নিতে পারি না
  • এটি COM ইন্টারপ জন্য সমর্থিত, যেমন নিবন্ধে প্রদর্শিত হয়েছে (গতিশীল প্রেরণ ব্যবহার করে)
  • এটি VB.NET এ প্রয়োগ করা হয়েছে
  • ইন্ডেক্সার তৈরি করা ইতোমধ্যে সম্ভব, অর্থাত্‍ বস্তুতে নিজেই একটি সূচক প্রয়োগ করা, সুতরাং একই বৈশিষ্ট্যটি রেখে এবং কেবলমাত্র thisনামের নামের পরিবর্তে বৈশিষ্ট্যগুলিতে ধারণা প্রসারিত করা কোনও বড় বিষয় হবে না

এটি এ জাতীয় জিনিস লিখতে দেয়:

public class Foo
{
    private string[] _values = new string[3];
    public string Values[int index]
    {
        get { return _values[index]; }
        set { _values[index] = value; }
    }
}

বর্তমানে আমি জানি যে একমাত্র কার্যতালিকা হ'ল একটি অভ্যন্তর শ্রেণি তৈরি করা ( ValuesCollectionউদাহরণস্বরূপ) যা কোনও সূচক প্রয়োগ করে এবং Valuesসম্পত্তি পরিবর্তন করে যাতে এটি সেই অভ্যন্তর শ্রেণীর উদাহরণ দেয় returns

এটি করা খুব সহজ, তবে বিরক্তিকর ... সুতরাং সম্ভবত সংকলকটি এটি আমাদের জন্য করতে পারে! একটি বিকল্প হ'ল একটি অভ্যন্তরীণ শ্রেণি তৈরি করা যা সূচকটি কার্যকর করে এবং একটি পাবলিক জেনেরিক ইন্টারফেসের মাধ্যমে প্রকাশ করে:

// interface defined in the namespace System
public interface IIndexer<TIndex, TValue>
{
    TValue this[TIndex index]  { get; set; }
}

public class Foo
{
    private string[] _values = new string[3];

    private class <>c__DisplayClass1 : IIndexer<int, string>
    {
        private Foo _foo;
        public <>c__DisplayClass1(Foo foo)
        {
            _foo = foo;
        }

        public string this[int index]
        {
            get { return _foo._values[index]; }
            set { _foo._values[index] = value; }
        }
    }

    private IIndexer<int, string> <>f__valuesIndexer;
    public IIndexer<int, string> Values
    {
        get
        {
            if (<>f__valuesIndexer == null)
                <>f__valuesIndexer = new <>c__DisplayClass1(this);
            return <>f__valuesIndexer;
        }
    }
}

তবে অবশ্যই, সেই ক্ষেত্রে সম্পত্তিটি আসলে ফিরে আসবেIIndexer<int, string> , এবং সত্যিকার অর্থেই কোনও সূচকযুক্ত সম্পত্তি হবে না ... আসল সিএলআর সূচিকৃত সম্পত্তি উত্পন্ন করা ভাল be

আপনি কি মনে করেন ? আপনি কি এই বৈশিষ্ট্যটি সি # তে দেখতে চান? তা না হলে কেন?


4
আমি অনুভূতি পেতে এই সেই অন্য এক "আমরা X এর জন্য অনুরোধ পেতে কিন্তু ওয়াই চেয়ে না আরো" সমস্যা।
কেওসপ্যান্ডিয়ন

4
@ চাওসপ্যান্ডিয়ন, হ্যাঁ, আপনি সম্ভবত ঠিক বলেছেন ... তবে এই বৈশিষ্ট্যটি সম্ভবত প্রয়োগ করা বেশ সহজ হবে এবং যদিও এটি অবশ্যই "অবশ্যই" নয় তবে এটি অবশ্যই "ভাল
লাগছে

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

4
@tk_ আপনার গঠনমূলক মন্তব্যের জন্য ধন্যবাদ। আপনি কি ফ্রি পাস্কাল নয় এমন ভাষা সম্পর্কে সমস্ত পোস্টে একই রকম মন্তব্য পোস্ট করছেন? ঠিক আছে, আমি আশা করি এটি আপনাকে নিজের সম্পর্কে ভাল বোধ করবে ...
টমাস লেভস্ক

4
এটি এমন কয়েকটি পরিস্থিতির মধ্যে একটি যেখানে C ++ / CLI এবং VB.net সি # এর চেয়ে ভাল। আমি আমার সি ++ / সিএলআই কোডগুলিতে প্রচুর সূচিকাগুলি প্রয়োগ করেছি এবং এখন এটিকে সি # তে রূপান্তর করার সময় তাদের সকলের জন্য কাজের সন্ধান করতে হবে। :-( SUCKS !!! // আপনার মাধ্যমে এই ধরণের জিনিসগুলি লিখতে দেওয়া হ'ল আমি বছরের পর বছর ধরে যা করেছি
টোবিয়াস কানাউস

উত্তর:


122

এখানে আমরা সি # 4 ডিজাইন করেছি।

প্রথমে আমরা ভাষায় যুক্ত করার কথা ভাবতে পারে এমন প্রতিটি সম্ভাব্য বৈশিষ্ট্যের একটি তালিকা তৈরি করেছিলাম।

তারপরে আমরা বৈশিষ্ট্যগুলিকে "এটি খারাপ, আমাদের কখনই এটি করা উচিত নয়", "এটি দুর্দান্ত কাজ, আমাদের এটি করতে হবে", এবং "এটি ভাল তবে এবার এটি করা যাক না" এ বৈশিষ্ট্যগুলি বুক করা হয়েছিল।

তারপরে আমরা "বাজে আছে" বৈশিষ্ট্যগুলি ডিজাইন, বাস্তবায়ন, পরীক্ষা, নথিপত্র শিপিং এবং বজায় রাখতে আমাদের কতটা বাজেট ছিল তা দেখেছি এবং আবিষ্কার করেছি যে আমরা বাজেটের চেয়ে 100% বেশি।

সুতরাং আমরা "গট হ্যাভ" বালতি থেকে "বালিতে ভাল লাগছে" বালতিতে একগুচ্ছ জিনিসপত্র সরিয়ে নিয়েছি।

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

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


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

11
এবং আশা করি স্বয়ংক্রিয়ভাবে প্রয়োগ করা INotifyPropertyChanged তালিকাভুক্ত বৈশিষ্ট্যগুলির চেয়ে তালিকায় আরও বেশি। :)
জোশ

4
@ এরিক, ঠিক আছে, এটাই আমার সন্দেহ হয়েছিল ... যাইহোক উত্তর দেওয়ার জন্য ধন্যবাদ! আমি অনুমান করি যে আমি বছরের পর বছর ধরে যেমন করেছি, ততক্ষণে আমি সূচিবদ্ধ সম্পত্তি ছাড়া বাঁচতে পারি;)
টমাস লেভস্ক

4
@ মার্টিন: বড় সফ্টওয়্যার দলগুলি কীভাবে বাজেট নির্ধারণ করা হয় সে সম্পর্কে আমি বিশেষজ্ঞ নই। আপনার প্রশ্নটি সোমা, জেসন জেন্ডার বা স্কট উইল্টমুথের দিকে সম্বোধন করা উচিত, আমি বিশ্বাস করি যাদের মাঝে মাঝে ব্লগ লেখেন। স্কালার সাথে আপনার তুলনা একটি আপেল থেকে কমলা তুলনা; সি # এর বেশিরভাগ ব্যয় স্কালায় থাকে না; কেবল একটি নাম রাখার জন্য, এর লক্ষ লক্ষ ব্যবহারকারীর অত্যন্ত গুরুত্বপূর্ণ পিছনের সামঞ্জস্যতার প্রয়োজনীয়তা নেই। আমি আপনাকে আরও অনেক কারণের নাম দিতে পারি যা সি # এবং স্কালার মধ্যে প্রচুর ব্যয়ের পার্থক্য তৈরি করতে পারে।
এরিক লিপার্ট

12
+1: লোকেরা এটি পড়ার মাধ্যমে সফ্টওয়্যার প্রকল্পগুলি পরিচালনা করার বিষয়ে অনেক কিছু জানতে পারে। এবং এটি কেবল কয়েক লাইন দীর্ঘ।
ব্রায়ান ম্যাকেয়ে

22

এসি # indexer হয় একটি সূচীবদ্ধ সম্পত্তি। এটি Itemডিফল্টরূপে নামকরণ করা হয়েছে (এবং আপনি এটি উদাহরণস্বরূপ ভিবি থেকে উল্লেখ করতে পারেন), এবং আপনি চাইলে এটি সূচক নামঅ্যাট্রিবিউটের সাহায্যে এটি পরিবর্তন করতে পারেন।

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


4
ধন্যবাদ! COM ইন্টারপ ইন্টারফেসগুলি প্রয়োগ করার সময় আমি বার বার ত্রুটিগুলির সাথে লড়াই করেছি যেগুলি একটি ডিফল্ট ইনডেসার (ডিআইএসপিআইডি 0) যা এই [অন্তর্] হিসাবে আমদানি করে তবে যার নাম মূলত "আইটেম" ছিল না (কখনও কখনও এটি "আইটেম" বা "মান", বা অনুরূপ) )। এটি যেকোনোভাবেই সংকলন করে এবং চালিত হয়, তবে নামটি পুরোপুরি খাপ খায় না বলে FxCop CA1033 ইন্টারফেসমেথডস শোল্ডডবেকল্যাবলবাইচিল্ড টাইপস সতর্কতা, সিএলএস-সম্মতি সংক্রান্ত ইস্যু (কেবলমাত্র ক্ষেত্রে পৃথক পৃথক পৃথক পৃথক পৃথক পৃথক) ইত্যাদি বাড়ে। [ইনডেক্সেরনাম] যা প্রয়োজন ছিল তা সবই, তবে আমি এটি কখনই খুঁজে পেতে পারি না।
puetzk

ধন্যবাদ!!! ইনডেক্সনার নাম বৈশিষ্ট্যটি আমাকে এমএসআইএল স্বাক্ষরগুলি ভঙ্গ না করে কোনও ভিবি সমাবেশকে সি # তে রূপান্তরিত করার অনুমতি দেয়।
জন তিরজান

15

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

class Foo
{
    public Values Values { ... }
}

class Values
{
    public string this[int index] { ... }    
}

foo.Values[0]

আমি ব্যক্তিগতভাবে 10 উপায়ের পরিবর্তে কিছু করার একক উপায় দেখতে পছন্দ করি। তবে অবশ্যই এটি একটি বিষয়গত মতামত।


4
+1, ভিবি 5 কনস্ট্রাক্টসের সাহায্যে ভাষা জাগ্রত করার চেয়ে এটি প্রয়োগের এটি একটি আরও ভাল উপায়।
জোশ

4
+1 কারণ আমি এটি এটি করব। এবং আপনি ভাল থাকলে আপনি সম্ভবত এই জেনেরিক তৈরি করতে পারেন।
টনি

10
এই পদ্ধতির সাথে একটি সমস্যা হ'ল অন্য কোডগুলির পক্ষে সূচকের অনুলিপি তৈরি করা সম্ভব হয় এবং এটি শব্দার্থতন্ত্রের কী হয় তা স্পষ্ট নয় it কোড যদি "var ব্যবহারকারীলিস্ট = Foo.User; Foo.RemoveSomeUser (); কিছু ব্যবহারকারী = ব্যবহারকারী তালিকা [5] বলে;" এটাই কি ফু (এলিমেন্টসুউজারের আগে) এর উপাদান [5] হিসাবে ব্যবহৃত হত, বা তার পরে? যদি কোনও ব্যবহারকারীলিস্ট [] যদি একটি সূচকযুক্ত সম্পত্তি হয় তবে এটি সরাসরি প্রকাশ করা হবে না।
সুপারক্যাট

আপনি কি স্থানান্তরের বরাদ্দ পছন্দ করেন?
জোশুয়া

9

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

ধারণাটি যৌক্তিক তবে এটি কেবল নমনীয়তা এবং আকস্মিক বিশ্রীতার দিকে নিয়ে যায়।


আকর্ষণীয় চিন্তাভাবনা, উত্তরটি কিছুটা দেরিতে হলেও;)। আপনি খুব ভাল পয়েন্ট তৈরি করছেন, +1।
টমাস লেভেস্ক

Vb.net- তে কোনও শ্রেণীর একই নামের একটি সূচকযুক্ত এবং অ-সূচিযুক্ত সম্পত্তি উভয়ই থাকতে পারে [যেমন Bar]। অভিব্যক্তি Thing.Bar(5)সূচীবদ্ধ সম্পত্তি ব্যবহার করেন Barউপর Thing, যখন (Thing.Bar)(5)অ সূচীবদ্ধ সম্পত্তি ব্যবহার করেন Barএবং তারপর ফলে বস্তুর ডিফল্ট indexer ব্যবহার করুন। আমার বাঁধাই করার ফলে Thing.Bar[5]একটি সম্পত্তি হতে Thingএকটি সম্পত্তি বদলে Thing.Barহয় ভাল, যেহেতু অন্যান্য বিষয়ের মধ্যে, এটা যে সময় কিছু মুহূর্তে অর্থ সম্ভব Thing.Bar[4]স্পষ্ট হতে পারে, কিন্তু সঠিক প্রভাব ...
সুপারক্যাট

... এর মতো কিছু var temp=Thing.Bar; do_stuff_with_thing; var q=temp[4]অস্পষ্ট হতে পারে। এমন একটি ধারণাও বিবেচনা করুন যা কোনও ক্ষেত্রের Thingডেটা ধরে রাখতে Barপারে যা কোনও অংশীদারি অপরিবর্তনীয় বস্তু বা একটি ভাগ না করা পার্সোনাল অবজেক্ট হতে পারে; Barযখন ব্যাকিং ফিল্ড অপরিবর্তনীয় তখন লিখতে চেষ্টা করার জন্য একটি পরিবর্তনীয় অনুলিপি তৈরি করা উচিত, তবে এটি থেকে পড়ার চেষ্টা করা উচিত নয়। যদি Barএকটি নামযুক্ত সূচকযুক্ত সম্পত্তি হয় তবে সূচকযুক্ত প্রাপ্ত ব্যক্তি ব্যাকিং সংগ্রহটি একা ছেড়ে দিতে পারতেন (পরিবর্তনীয় বা না হোক) যখন সেটার প্রয়োজনে একটি নতুন পরিবর্তনীয় অনুলিপি তৈরি করতে পারে।
সুপারক্যাট

কোনও সম্পত্তির সূচক কোনও
গণক

6

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

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

যদি সূচকযুক্ত বৈশিষ্ট্যগুলি সি # তে উপলব্ধ থাকত তবে আমি নীচের কোডটি প্রয়োগ করতে পারতাম (সিনট্যাক্সটি হ'ল এটি [কী] প্রপার্টিনেম [কী] তে পরিবর্তিত হয়েছে)।

public interface IConfig
{
    // Other configuration properties removed for examp[le

    /// <summary>
    /// Script fragments
    /// </summary>
    string Scripts[string name] { get; set; }
}

/// <summary>
/// Class to handle loading and saving the application's configuration.
/// </summary>
internal class Config : IConfig, IXmlConfig
{
  #region Application Configuraiton Settings

    // Other configuration properties removed for examp[le

    /// <summary>
    /// Script fragments
    /// </summary>
    public string Scripts[string name]
    {
        get
        {
            if (!string.IsNullOrWhiteSpace(name))
            {
                string script;
                if (_scripts.TryGetValue(name.Trim().ToLower(), out script))
                    return script;
            }
            return string.Empty;
        }
        set
        {
            if (!string.IsNullOrWhiteSpace(name))
            {
                _scripts[name.Trim().ToLower()] = value;
                OnAppConfigChanged();
            }
        }
    }
    private readonly Dictionary<string, string> _scripts = new Dictionary<string, string>();

  #endregion

    /// <summary>
    /// Clears configuration settings, but does not clear internal configuration meta-data.
    /// </summary>
    private void ClearConfig()
    {
        // Other properties removed for example
        _scripts.Clear();
    }

  #region IXmlConfig

    void IXmlConfig.XmlSaveTo(int configVersion, XElement appElement)
    {
        Debug.Assert(configVersion == 2);
        Debug.Assert(appElement != null);

        // Saving of other properties removed for example

        if (_scripts.Count > 0)
        {
            var scripts = new XElement("Scripts");
            foreach (var kvp in _scripts)
            {
                var scriptElement = new XElement(kvp.Key, kvp.Value);
                scripts.Add(scriptElement);
            }
            appElement.Add(scripts);
        }
    }

    void IXmlConfig.XmlLoadFrom(int configVersion, XElement appElement)
    {
        // Implementation simplified for example

        Debug.Assert(appElement != null);
        ClearConfig();
        if (configVersion == 2)
        {
            // Loading of other configuration properites removed for example

            var scripts = appElement.Element("Scripts");
            if (scripts != null)
                foreach (var script in scripts.Elements())
                    _scripts[script.Name.ToString()] = script.Value;
        }
        else
            throw new ApplicaitonException("Unknown configuration file version " + configVersion);
    }

  #endregion
}

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

আমি এটিকে বাস্তবায়ন করতে পারতাম:

public string ScriptGet(string name)
public void ScriptSet(string name, string value)

যা আমার সম্ভবত হওয়া উচিত, তবে কেন এই অনুপস্থিত বৈশিষ্ট্যের প্রতিস্থাপন হিসাবে সূচিকৃত ক্লাস ব্যবহার করা প্রায়শই যুক্তিসঙ্গত বিকল্প নয়।

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

public interface IConfig
{
    // Other configuration properties removed for examp[le

    /// <summary>
    /// Script fragments
    /// </summary>
    ScriptsCollection Scripts { get; }
}

/// <summary>
/// Class to handle loading and saving the application's configuration.
/// </summary>
internal class Config : IConfig, IXmlConfig
{
    public Config()
    {
        _scripts = new ScriptsCollection();
        _scripts.ScriptChanged += ScriptChanged;
    }

  #region Application Configuraiton Settings

    // Other configuration properties removed for examp[le

    /// <summary>
    /// Script fragments
    /// </summary>
    public ScriptsCollection Scripts
    { get { return _scripts; } }
    private readonly ScriptsCollection _scripts;

    private void ScriptChanged(object sender, ScriptChangedEventArgs e)
    {
        OnAppConfigChanged();
    }

  #endregion

    /// <summary>
    /// Clears configuration settings, but does not clear internal configuration meta-data.
    /// </summary>
    private void ClearConfig()
    {
        // Other properties removed for example
        _scripts.Clear();
    }

  #region IXmlConfig

    void IXmlConfig.XmlSaveTo(int configVersion, XElement appElement)
    {
        Debug.Assert(configVersion == 2);
        Debug.Assert(appElement != null);

        // Saving of other properties removed for example

        if (_scripts.Count > 0)
        {
            var scripts = new XElement("Scripts");
            foreach (var kvp in _scripts)
            {
                var scriptElement = new XElement(kvp.Key, kvp.Value);
                scripts.Add(scriptElement);
            }
            appElement.Add(scripts);
        }
    }

    void IXmlConfig.XmlLoadFrom(int configVersion, XElement appElement)
    {
        // Implementation simplified for example

        Debug.Assert(appElement != null);
        ClearConfig();
        if (configVersion == 2)
        {
            // Loading of other configuration properites removed for example

            var scripts = appElement.Element("Scripts");
            if (scripts != null)
                foreach (var script in scripts.Elements())
                    _scripts[script.Name.ToString()] = script.Value;
        }
        else
            throw new ApplicaitonException("Unknown configuration file version " + configVersion);
    }

  #endregion
}

public class ScriptsCollection : IEnumerable<KeyValuePair<string, string>>
{
    private readonly Dictionary<string, string> Scripts = new Dictionary<string, string>();

    public string this[string name]
    {
        get
        {
            if (!string.IsNullOrWhiteSpace(name))
            {
                string script;
                if (Scripts.TryGetValue(name.Trim().ToLower(), out script))
                    return script;
            }
            return string.Empty;
        }
        set
        {
            if (!string.IsNullOrWhiteSpace(name))
                Scripts[name.Trim().ToLower()] = value;
        }
    }

    public void Clear()
    {
        Scripts.Clear();
    }

    public int Count
    {
        get { return Scripts.Count; }
    }

    public event EventHandler<ScriptChangedEventArgs> ScriptChanged;

    protected void OnScriptChanged(string name)
    {
        if (ScriptChanged != null)
        {
            var script = this[name];
            ScriptChanged.Invoke(this, new ScriptChangedEventArgs(name, script));
        }
    }

  #region IEnumerable

    public IEnumerator<KeyValuePair<string, string>> GetEnumerator()
    {
        return Scripts.GetEnumerator();
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        return GetEnumerator();
    }

  #endregion
}

public class ScriptChangedEventArgs : EventArgs
{
    public string Name { get; set; }
    public string Script { get; set; }

    public ScriptChangedEventArgs(string name, string script)
    {
        Name = name;
        Script = script;
    }
}

2

আর একটি কাজের ভিত্তিতে বৈশিষ্ট্যগুলি সহজেই তৈরিতে তালিকাভুক্ত করা হয়েছে যা সি # তে সূচকে সমর্থন করে , এর জন্য কম কাজ প্রয়োজন।

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


4
আপনার সম্পাদনার উত্তরে: আমি মনে করি না যে এটি ভাষা ফেটে যাবে; বাক্য গঠনটি ইতিমধ্যে শ্রেণি সূচক ( this[]) এর জন্য রয়েছে, তাদের কেবল পরিবর্তে একটি শনাক্তকারীকে অনুমতি দেওয়া দরকার this। তবে আমি সন্দেহ করি যে এরিক তার উত্তরে যে কারণগুলি ব্যাখ্যা করেছেন
থমাস লেভেস্ক

1

ঠিক আছে আমি বলব যে তারা এটিকে যুক্ত করেনি কারণ এটি ডিজাইনিং, বাস্তবায়ন, পরীক্ষা এবং ডকুমেন্টিংয়ের ব্যয়বহুল ছিল না।

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

আপনি এটি উল্লেখ করতে ভুলে গেছেন যে একটি সহজ কাজটি কেবল একটি নিয়মিত পদ্ধতি তৈরি করা হয়:

public void SetFoo(int index, Foo toSet) {...}
public Foo GetFoo(int index) {...}

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

1

সূচক কার্যকারিতা প্রক্সি করতে ল্যাম্বডাস ব্যবহার করে একটি সাধারণ সাধারণ সমাধান রয়েছে

কেবল সূচকের পাঠের জন্য

public class RoIndexer<TIndex, TValue>
{
    private readonly Func<TIndex, TValue> _Fn;

    public RoIndexer(Func<TIndex, TValue> fn)
    {
        _Fn = fn;
    }

    public TValue this[TIndex i]
    {
        get
        {
            return _Fn(i);
        }
    }
}

পরিবর্তনীয় সূচক জন্য

public class RwIndexer<TIndex, TValue>
{
    private readonly Func<TIndex, TValue> _Getter;
    private readonly Action<TIndex, TValue> _Setter;

    public RwIndexer(Func<TIndex, TValue> getter, Action<TIndex, TValue> setter)
    {
        _Getter = getter;
        _Setter = setter;
    }

    public TValue this[TIndex i]
    {
        get
        {
            return _Getter(i);
        }
        set
        {
            _Setter(i, value);
        }
    }
}

এবং একটি কারখানা

public static class Indexer
{
    public static RwIndexer<TIndex, TValue> Create<TIndex, TValue>(Func<TIndex, TValue> getter, Action<TIndex, TValue> setter)
    {
        return new RwIndexer<TIndex, TValue>(getter, setter);
    } 
    public static RoIndexer<TIndex, TValue> Create<TIndex, TValue>(Func<TIndex, TValue> getter)
    {
        return new RoIndexer<TIndex, TValue>(getter);
    } 
}

আমার নিজের কোডে আমি এটি পছন্দ করি

public class MoineauFlankContours
{

    public MoineauFlankContour Rotor { get; private set; }

    public MoineauFlankContour Stator { get; private set; }

     public MoineauFlankContours()
    {
        _RoIndexer = Indexer.Create(( MoineauPartEnum p ) => 
            p == MoineauPartEnum.Rotor ? Rotor : Stator);
    }
    private RoIndexer<MoineauPartEnum, MoineauFlankContour> _RoIndexer;

    public RoIndexer<MoineauPartEnum, MoineauFlankContour> FlankFor
    {
        get
        {
            return _RoIndexer;
        }
    }

}

এবং MoineauFlankContours এর উদাহরণ সহ আমি করতে পারি

MoineauFlankContour rotor = contours.FlankFor[MoineauPartEnum.Rotor];
MoineauFlankContour stator = contours.FlankFor[MoineauPartEnum.Stator];

চতুর, তবে প্রতিবার তৈরি করার পরিবর্তে সূচককে ক্যাশে দেওয়া ভাল;)
টমাস লেভস্ক

0

আমি নিজেও খুঁজে পেয়েছি যে আপনি এটি অর্জনের জন্য সুস্পষ্টভাবে প্রয়োগকৃত ইন্টারফেসগুলি ব্যবহার করতে পারেন, যেমন এখানে প্রদর্শিত: সি # তে তালিকাভুক্ত সংযুক্ত সম্পত্তি? (উত্তরটিতে দেখানো দ্বিতীয় উপায় দেখুন)

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