একক আইটেমটি IEnumerable <T> হিসাবে পাস করা


377

Tকোনও IEnumerable<T>পরামিতি প্রত্যাশা করে এমন কোনও পদ্ধতির কাছে কোনও একক আইটেম পাস করার কি সাধারণ উপায় আছে ? ভাষা সি #, ফ্রেমওয়ার্ক সংস্করণ 2.0।

বর্তমানে আমি একটি সহায়ক পদ্ধতি ব্যবহার করছি (এটি নেট ২.০, তাই আমার কাছে লাইনকিউয়ের অনুরূপ কাস্টিং / প্রজেক্টিং সহায়ক সহায়তা পদ্ধতি রয়েছে) তবে এটি কেবল নির্বোধ বলে মনে হচ্ছে:

public static class IEnumerableExt
{
    // usage: IEnumerableExt.FromSingleItem(someObject);
    public static IEnumerable<T> FromSingleItem<T>(T item)
    {
        yield return item; 
    }
}

অন্য উপায় অবশ্যই একটি List<T>বা একটি তৈরি এবং পপুলেট করা Arrayএবং পরিবর্তে এটি পাস করা হবে IEnumerable<T>

[সম্পাদনা] একটি এক্সটেনশন পদ্ধতি হিসাবে এর নাম দেওয়া যেতে পারে:

public static class IEnumerableExt
{
    // usage: someObject.SingleItemAsEnumerable();
    public static IEnumerable<T> SingleItemAsEnumerable<T>(this T item)
    {
        yield return item; 
    }
}

আমি কি এখানে কিছু মিস করছি?

[সম্পাদনা 2] আমরা খুঁজে পেয়েছি someObject.Yield()(নীচের মন্তব্যে @ পিটার প্রস্তাবিত হিসাবে) মূলত ব্রেভিটির জন্য এই এক্সটেনশন পদ্ধতির সেরা নাম হিসাবে দেখা গেছে, সুতরাং যদি কেউ এটি ধরতে চায় তবে এটি এক্সএমএল মন্তব্যের সাথে এখানে রয়েছে:

public static class IEnumerableExt
{
    /// <summary>
    /// Wraps this object instance into an IEnumerable&lt;T&gt;
    /// consisting of a single item.
    /// </summary>
    /// <typeparam name="T"> Type of the object. </typeparam>
    /// <param name="item"> The instance that will be wrapped. </param>
    /// <returns> An IEnumerable&lt;T&gt; consisting of a single item. </returns>
    public static IEnumerable<T> Yield<T>(this T item)
    {
        yield return item;
    }
}

6
আমি এক্সটেনশন পদ্ধতির শরীরে কিছুটা পরিবর্তন করব: if (item == null) yield break; এখন আপনাকে নাল ছাড়ার পাশাপাশি (তুচ্ছ) নাল বস্তুর প্যাটার্নটির সুবিধা গ্রহণ বন্ধ করে দেওয়া হয়েছে IEnumerable। ( foreach (var x in xs)খালি খালি xsজরিমানা করে)। ঘটনাক্রমে, এই ফাংশনটি তালিকা মোনাডের মোনাডিক ইউনিট IEnumerable<T>যা মাইক্রোসফ্টে মোনাদকে লাভ-ফেস্ট দেওয়া হয়েছে আমি অবাক হয়েছি এরকম কিছু প্রথম প্রথম কাঠামোর মধ্যে নেই।
ম্যাট এনরাট

2
এক্সটেনশন পদ্ধতির জন্য, আপনার নাম রাখা উচিত নয় AsEnumerableকারণ সেই নামের একটি অন্তর্নির্মিত এক্সটেনশন ইতিমধ্যে বিদ্যমান । (যখন Tপ্রয়োগগুলি IEnumerable, উদাহরণস্বরূপ string।)
জন-এরিক

22
পদ্ধতিটির নামকরণ কীভাবে Yield? কিছুই ব্রেভিটকে মারধর করে না।
ফিলিপ গিন

4
নামকরণ পরামর্শ এখানে। "একক আইটেমস গণনাযোগ্য" কিছুটা ভার্বোস। "ফলন" ইন্টারফেসের পরিবর্তে বাস্তবায়ন বর্ণনা করে - যা ভাল নয়। আরও ভাল নামের জন্য, আমি "এসসিংলেটন" পরামর্শ দিচ্ছি, যা আচরণের সঠিক অর্থের সাথে মিল রাখে।
আর্থ ইঞ্জিন

4
আমি left==nullএখানে চেক ঘৃণা করি । এটি কোডটির বিউটিটি ভেঙে দেয় এবং কোডটি আরও নমনীয় হওয়া বন্ধ করে দেয় - যদি কোনও দিন আপনি শালীন হতে পারে এমন কোনও কিছু নিয়ে একটি সিঙ্গলটন তৈরি করার দরকার পড়ে তবে কী হবে? মানে, new T[] { null }এর মতো নয় new T[] {}এবং কোনও কোনও দিন আপনাকে তাদের আলাদা করার প্রয়োজন হতে পারে।
আর্থ ইঞ্জিন

উত্তর:


100

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


ভাল যদি তালিকা / অ্যারেটি অ্যাড-হক তৈরি করা হয় তবে পদ্ধতি কলের পরে এর পরিধিটি শেষ হয়, সুতরাং এটি সমস্যার কারণ হবে না
মারিও এফ

যদি অ্যারে হিসাবে প্রেরণ করা হয় তবে কীভাবে এটি পরিবর্তন করা যায়? আমি অনুমান করি যে এটি কোনও অ্যারেতে ফেলে দেওয়া যেতে পারে এবং তারপরে অন্য কোনও কিছুতে রেফারেন্স পরিবর্তন করতে পারে তবে এটি কী ভাল করবে? (যদিও আমি সম্ভবত কিছু মিস করছি ...)
সুইভিশ

2
মনে করুন আপনি দুটি পৃথক পদ্ধতিতে পাস করার জন্য একটি গণনাকারী তৈরি করার সিদ্ধান্ত নিয়েছেন ... তারপরে প্রথমটি এটিকে অ্যারেতে ফেলেছে এবং সামগ্রীগুলি পরিবর্তন করেছে changed তারপরে আপনি এটিকে অন্য পদ্ধতির পক্ষে যুক্তি হিসাবে পাস করুন, পরিবর্তনটি অজানা। আমি সম্ভবত এটি বলছি না, ঠিক যে কিছু পরিবর্তনের দরকার নেই যখন নটুরলা অপরিবর্তনীয়তার চেয়ে কম ঝরঝরে হয়।
জন স্কিটি

3
এটি একটি স্বীকৃত উত্তর, এবং সম্ভবত পড়ার সম্ভাবনা রয়েছে, তাই আমি এখানে আমার উদ্বেগ যুক্ত করব। আমি এই পদ্ধতিটি চেষ্টা করেছিলাম, তবে এটি আমার আগের সংকলন কলটি myDict.Keys.AsEnumerable()যেখানে myDictটাইপ ছিল তা ভেঙে দিয়েছে Dictionary<CheckBox, Tuple<int, int>>। আমি এক্সটেনশন পদ্ধতিটির নামকরণ করার পরে SingleItemAsEnumerable, সমস্ত কিছু কাজ শুরু করে। আইনিউমারেবল <ডিকশনারি <চেকবক্স, সিস্টেম.টুপল <ইন, ইন্টার >> একটি সুস্পষ্ট রূপান্তর বিদ্যমান (আপনি কি একটি castালাই অনুপস্থিত?) আমি কিছুক্ষণের জন্য একটি হ্যাকের সাথে বেঁচে থাকতে পারি, তবে অন্য শক্তি হ্যাকাররা কী আরও ভাল উপায় খুঁজে পেতে পারে?
হামিশ গ্রুবিজন

3
@ হামিশগ্রুবিজান: মনে হচ্ছে আপনি কেবল dictionary.Valuesশুরু করতে চেয়েছিলেন । মূলত এটি কী চলছে তা পরিষ্কার নয়, তবে আমি আপনাকে এটি সম্পর্কে একটি নতুন প্রশ্ন শুরু করার পরামর্শ দিচ্ছি।
জন স্কিটি

133

ঠিক আছে, পদ্ধতিটি যদি আশা করে যে IEnumerableআপনি কোনও একটি তালিকা দিয়েছিলেন যা কেবল একটি উপাদান রয়েছে, এমনকি যদি এটিতে কেবল একটি উপাদান থাকে।

ক্ষণস্থায়ী

new[] { item }

যুক্তি হিসাবে যথেষ্ট মনে করা উচিত


32
আমি মনে করি আপনি
টিও

2
আমি মনে করি এটি সি # 2.0 তে অনুমান করা হয়নি।
গ্রো 13

4
"ভাষা হল সি #, ফ্রেমওয়ার্ক সংস্করণ 2" সি # 3 সংকলক টি অনুমান করতে পারে, এবং কোড। নেট 2 এর সাথে পুরোপুরি সামঞ্জস্যপূর্ণ হবে

সেরা উত্তর নীচে ?!
ফালকো আলেকজান্ডার

2
@ স্যুইশ আমি উত্তরটি দেওয়ার জন্য প্রস্তাবিত ও সম্পাদনা করেছি ঠিক তা করার জন্য - আমরা এখন ২০২০ এ আছি, সুতরাং এটি "মানক"
ইমো

120

সি # 3.0 এ আপনি সিস্টেমটি ব্যবহার করতে পারেন inলিনক.অনামযোগ্য শ্রেণী:

// using System.Linq

Enumerable.Repeat(item, 1);

এটি একটি নতুন আইমনামেবল তৈরি করবে যা কেবল আপনার আইটেমকে ধারণ করে।


26
আমি মনে করি যে এই সমাধানটি কোডটি পড়া আরও কঠিন করে তুলবে। :( একক উপাদানের উপর পুনরাবৃত্তি করা বেশ
স্ব

6
আমার কাছে আবার ঠিকঠাক পড়ে পুনরাবৃত্তি করুন। আরও একটি এক্সটেনশন পদ্ধতি যুক্ত করার চিন্তা না করেই সহজ সমাধান এবং আপনি যেখানেই এটি ব্যবহার করতে চান সেখানে নাম স্থানটি অন্তর্ভুক্ত করে তা নিশ্চিত করা।
si618

13
হ্যাঁ আমি আসলে new[]{ item }নিজেকে ব্যবহার করি, আমি কেবল ভেবেছিলাম এটি একটি আকর্ষণীয় সমাধান।
লুকসান

7
এই সমাধানটি অর্থ।
প্রোভেগা

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

35

সি # 3 এ (আমি জানি আপনি 2 বলেছেন), আপনি একটি জেনেরিক এক্সটেনশন পদ্ধতি লিখতে পারেন যা সিনট্যাক্সটিকে আরও কিছুটা গ্রহণযোগ্য করে তুলতে পারে:

static class IEnumerableExtensions
{
    public static IEnumerable<T> ToEnumerable<T>(this T item)
    {
        yield return item;
    }
}

ক্লায়েন্ট কোড হয় item.ToEnumerable()


ধন্যবাদ, আমি এটি সম্পর্কে অবগত (আমি সি # 3.0 ব্যবহার করি নেট 2.0 তে কাজ করে) আমি কেবল ভাবছিলাম যে এর জন্য কোনও বিল্ট ইন মেকানিজম রয়েছে কিনা।
গ্রো 13

12
এটি একটি দুর্দান্ত বিকল্প। আমি কেবল এর ToEnumerableসাথে System.Linq.Enumerable.AsEnumerable
জগাখিচুড়ি

3
পার্শ্ব নোট হিসাবে, ইতিমধ্যে এর ToEnumerableজন্য একটি এক্সটেনশন পদ্ধতি বিদ্যমান রয়েছে IObservable<T>, সুতরাং এই পদ্ধতির নামটি বিদ্যমান কনভেনশনগুলিতে হস্তক্ষেপ করে। সত্যি বলতে, আমি কোনও এক্সটেনশন পদ্ধতি ব্যবহার না করার পরামর্শ দিই কারণ এটি খুব জেনেরিক।
cwharris

14

এই সহায়ক পদ্ধতিটি আইটেম বা অনেকের জন্য কাজ করে।

public static IEnumerable<T> ToEnumerable<T>(params T[] items)
{
    return items;
}    

1
দরকারী প্রকরণ, যেহেতু এটি একাধিক আইটেমকে সমর্থন করে। আমি এটি পছন্দ করি যে এটি paramsঅ্যারে তৈরি করতে নির্ভর করে , ফলে ফলাফলটি পরিষ্কার-চেহারাযুক্ত। আমি new T[]{ item1, item2, item3 };একাধিক আইটেমের চেয়ে কম-বেশি পছন্দ করব কিনা তা স্থির করেনি ।
টুলমেকারস্টেভ

স্মার্ট! এটি পছন্দ করুন
মিতসুরু ফুরুতা

10

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

public void DoSomething<T>(IEnumerable<T> list)
{
    // Do Something
}

public void DoSomething<T>(T item)
{
    DoSomething(new T[] { item });
}

এখন আপনার ক্লায়েন্ট কোডটি এটি করতে পারে:

MyItem item = new MyItem();
Obj.DoSomething(item);

বা একটি তালিকা সহ:

List<MyItem> itemList = new List<MyItem>();
Obj.DoSomething(itemList);

19
আরও ভাল, আপনার DoSomething<T>(params T[] items)কাছে এটির অর্থ হতে পারে যার অর্থ সংকলক একক আইটেম থেকে অ্যারেতে রূপান্তর পরিচালনা করবে। (এটি আপনাকে একাধিক পৃথক আইটেমগুলিতে পাস করার অনুমতি দেবে এবং,
সংকলকটি এগুলি

7

হয় (যেমন আগে বলা হয়েছে)

MyMethodThatExpectsAnIEnumerable(new[] { myObject });

অথবা

MyMethodThatExpectsAnIEnumerable(Enumerable.Repeat(myObject, 1));

পার্শ্ব নোট হিসাবে, আপনি যদি কোনও বেনামে থাকা অবজেক্টের খালি তালিকা চান তবে সর্বশেষ সংস্করণটিও দুর্দান্ত হতে পারে

var x = MyMethodThatExpectsAnIEnumerable(Enumerable.Repeat(new { a = 0, b = "x" }, 0));

ধন্যবাদ, যদিও গণনাযোগ্য ..Net 3.5 এ পুনরাবৃত্তি নতুন। এটি উপরের সহায়ক পদ্ধতির অনুরূপ আচরণ করে বলে মনে হচ্ছে।
গ্রো 13

7

যেমনটি আমি সবেমাত্র পেয়েছি এবং দেখেছি যে লুক্ক এই ব্যবহারকারী পরামর্শ দিয়েছে, এটি করার একটি দুর্দান্ত সহজ উপায় নীচে:

public static void PerformAction(params YourType[] items)
{
    // Forward call to IEnumerable overload
    PerformAction(items.AsEnumerable());
}

public static void PerformAction(IEnumerable<YourType> items)
{
    foreach (YourType item in items)
    {
        // Do stuff
    }
}

এই নিদর্শন আপনাকে বহু উপায়ে একই কার্যকারিতা কল করতে অনুমতি দেবে: একটি একক আইটেম; একাধিক আইটেম (কমা দ্বারা পৃথক); একটি অ্যারের; একটি তালিকা; একটি গণনা, ইত্যাদি

যদিও আমি AsEnumerable পদ্ধতি ব্যবহারের দক্ষতার বিষয়ে 100% নিশ্চিত নই, তবে এটি একটি ট্রিট কাজ করে।

আপডেট: অসমাপ্ত ফাংশনটি বেশ দক্ষ দেখায়! ( রেফারেন্স )


আসলে, আপনার মোটেই দরকার নেই .AsEnumerable()। অ্যারে YourType[]ইতিমধ্যে প্রয়োগ করে IEnumerable<YourType>। তবে আমার প্রশ্নটি সেই ক্ষেত্রে উল্লেখ করছে যখন কেবলমাত্র দ্বিতীয় পদ্ধতিটি (আপনার উদাহরণে) উপলব্ধ থাকে এবং আপনি .NET 2.0 ব্যবহার করেন এবং আপনি একটি আইটেম পাস করতে চান।
গ্রু

2
হ্যাঁ, এটি হয় তবে আপনি দেখতে পাবেন যে আপনি একটি স্ট্যাক ওভারফ্লো করতে পারেন ;-)
teppicymon

এবং প্রকৃতপক্ষে আপনার আসল প্রশ্নের উত্তর দেওয়ার জন্য (আমি নিজেই নিজের উত্তরটির জন্য যা খুঁজছিলাম তা নয়!) হ্যাঁ, আপনাকে
মারিওয়ের

2
কিভাবে একটি IEnumerable<T> MakeEnumerable<T>(params T[] items) {return items;}পদ্ধতি সংজ্ঞায়িত সম্পর্কে ? এর পরে যে কোনওটি প্রত্যাশাযুক্ত যে IEnumerable<T>কোনও সংখ্যক বিযুক্ত আইটেমের সাথে এটি ব্যবহার করতে পারে । কোডটি কোনও আইটেম ফেরত দেওয়ার জন্য একটি বিশেষ শ্রেণীর সংজ্ঞা দেওয়ার মতো কার্যকরভাবে হওয়া উচিত।
সুপারক্যাট

6

যদিও এটি একটি পদ্ধতির জন্য ওভারকিল, তবুও আমি বিশ্বাস করি কিছু লোক ইন্টারেক্টিভ এক্সটেনশানগুলি দরকারী বলে মনে করতে পারে।

মাইক্রোসফ্ট থেকে ইন্টারেক্টিভ এক্সটেনশনস (আইএক্স) নিম্নলিখিত পদ্ধতি অন্তর্ভুক্ত করে।

public static IEnumerable<TResult> Return<TResult>(TResult value)
{
    yield return value;
}

যা এর মতো ব্যবহার করা যেতে পারে:

var result = EnumerableEx.Return(0);

Ix মূল লিনক এক্সটেনশন পদ্ধতিতে পাওয়া যায় নি এমন নতুন কার্যকারিতা যুক্ত করে এবং প্রতিক্রিয়াশীল এক্সটেনশনগুলি (আরএক্স) তৈরির প্রত্যক্ষ ফলাফল।

ভাবুন, Linq Extension Methods+ Ix= এর Rxজন্য IEnumerable

আপনি কোডপ্লেক্সে আরএক্স এবং আইএক্স উভয়ই খুঁজে পেতে পারেন ।


5

এই 30% চেয়ে দ্রুত yieldবা Enumerable.Repeatযখন ব্যবহৃত foreachকারণে এই সি # কম্পাইলার অপ্টিমাইজেশান , এবং অন্যান্য ক্ষেত্রে একই কর্মক্ষমতা।

public struct SingleSequence<T> : IEnumerable<T> {
    public struct SingleEnumerator : IEnumerator<T> {
        private readonly SingleSequence<T> _parent;
        private bool _couldMove;
        public SingleEnumerator(ref SingleSequence<T> parent) {
            _parent = parent;
            _couldMove = true;
        }
        public T Current => _parent._value;
        object IEnumerator.Current => Current;
        public void Dispose() { }

        public bool MoveNext() {
            if (!_couldMove) return false;
            _couldMove = false;
            return true;
        }
        public void Reset() {
            _couldMove = true;
        }
    }
    private readonly T _value;
    public SingleSequence(T value) {
        _value = value;
    }
    public IEnumerator<T> GetEnumerator() {
        return new SingleEnumerator(ref this);
    }
    IEnumerator IEnumerable.GetEnumerator() {
        return new SingleEnumerator(ref this);
    }
}

এই পরীক্ষায়:

    // Fastest among seqs, but still 30x times slower than direct sum
    // 49 mops vs 37 mops for yield, or c.30% faster
    [Test]
    public void SingleSequenceStructForEach() {
        var sw = new Stopwatch();
        sw.Start();
        long sum = 0;
        for (var i = 0; i < 100000000; i++) {
            foreach (var single in new SingleSequence<int>(i)) {
                sum += single;
            }
        }
        sw.Stop();
        Console.WriteLine($"Elapsed {sw.ElapsedMilliseconds}");
        Console.WriteLine($"Mops {100000.0 / sw.ElapsedMilliseconds * 1.0}");
    }

ধন্যবাদ, টাইট লুপগুলিতে জিসি বোঝা হ্রাস করার জন্য এই ক্ষেত্রে একটি কাঠামো তৈরি করা অর্থপূর্ণ।
গ্রো 10

1
পুনরায় এবং গণনাযোগ্য উভয়ই বাক্সবন্দী হতে চলেছেন ....
স্টিফেন ড্রু

2
স্টপওয়াচ ব্যবহার করে তুলনা করবেন না। বেঞ্চমার্ক.নেট github.com/dotnet/BenchmarkDotNet
NN_

1
কেবল এটি পরিমাপ করা হয়েছে এবং new [] { i }বিকল্পটি আপনার বিকল্পটি প্রায় 3.2 গুণ বেশি দ্রুত। এছাড়াও আপনার বিকল্পটি প্রায় 1.2 গুণ বেশি দ্রুত এবং এর সাথে এক্সটেনশনটি বাড়ায় yield return
লোরন্ড

আপনি অন্য সি # সংকলক অপটিমাইজেশন ব্যবহার করে এটির গতি বাড়িয়ে তুলতে পারেন: SingleEnumerator GetEnumerator()এমন একটি পদ্ধতি যুক্ত করুন যা আপনার স্ট্রাক্টকে ফেরত দেয়। সি # সংকলক ইন্টারফেসের পরিবর্তে এই পদ্ধতিটি ব্যবহার করবে (এটি হাঁসের টাইপিংয়ের মাধ্যমে দেখায়) এবং বক্সিংটি এড়িয়ে চলে। অনেকগুলি অন্তর্নির্মিত সংগ্রহগুলি তালিকার মতো এই কৌশলটি ব্যবহার করে । দ্রষ্টব্য: এটি কেবল তখনই কাজ করবে যখন SingleSequenceআপনার উদাহরণের মতো প্রত্যক্ষ প্রত্যাহার করুন। আপনি যদি এটি কোনও IEnumerable<>ভেরিয়েবলে সংরক্ষণ করেন তবে কৌশলটি কাজ করবে না (ইন্টারফেস পদ্ধতিটি ব্যবহৃত হবে)
এঞ্জি

5

IanG হয়েছে বিষয়ে একটি ভাল পোস্ট , পরামর্শ EnumerableFrom()(এবং উল্লেখ করেছেন যে Haskell, এবং Rx সেটিতে কল নামের Return)। আইআইআরসি এফ # এটিকে রিটার্নও বলে । এফ # এর Seqঅপারেটরকে কল করেsingleton<'T>

আপনি সি #-কেন্দ্রীক হওয়ার জন্য প্রস্তুত থাকলে লোভনীয় হ'ল এটিকে Yield[ yield returnএটি উপলব্ধি করার সাথে জড়িতদের ইঙ্গিত দেওয়া ]]

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


4

এটি এর চেয়ে ভাল আর নাও হতে পারে তবে এটি এক ধরণের শীতল:

Enumerable.Range(0, 1).Select(i => item);

এটা না। এটা ভিন্ন.
নওফাল

Ewww। এটি কেবলমাত্র একটি আইটেমকে একটি গণনাকারী রূপান্তরিত করার জন্য বিশদ।
টুলমেকারস্টেভ

1
এটি প্রাতঃরাশ তৈরির জন্য রুবে গোল্ডবার্গ মেশিন ব্যবহারের সমতুল্য । হ্যাঁ এটি কাজ করে তবে সেখানে পৌঁছানোর জন্য এটি 10 ​​টি হুপের মধ্য দিয়ে লাফিয়ে। লক্ষ লক্ষ বার মৃত্যুদণ্ড কার্যকর করা এমন টাইট লুপে কাজ করার পরে এর মতো একটি সাধারণ কাজটি পারফরম্যান্স বাধা হতে পারে। অনুশীলনে, পারফরম্যান্স দিকটি 99% ক্ষেত্রে ক্ষেত্রে কিছু যায় আসে না, তবে ব্যক্তিগতভাবে আমি এখনও মনে করি এটি সম্পূর্ণ অপ্রয়োজনীয় ওভারকিল।
enzi

4

আমি আসল পোস্টে @ আর্থেনগাইনের মন্তব্যগুলির সাথে একমত, যা 'এসসিংটন' একটি ভাল নাম। এই উইকিপিডিয়া এন্ট্রি দেখুন । তারপরে এটি সিঙ্গেলনের সংজ্ঞা থেকে এসেছে যে একটি নাল মান যদি এই যুক্তি হিসাবে পাস করা হয় যে 'এসসিংটন' খালি আইইনুমেবলের পরিবর্তে একটি নাল মান দিয়ে একটি আইমনামেবল ফিরিয়ে দেবে যা if (item == null) yield break;বিতর্ক নিষ্পত্তি করবে । আমি মনে করি সবচেয়ে ভাল সমাধান হ'ল দুটি পদ্ধতি রয়েছে: 'অ্যাসিংটেলটন' এবং 'এসিংসলেটোনঅরম্পটি'; যেখানে, নালটিকে তর্ক হিসাবে পাস করার ক্ষেত্রে, 'এসসিংটন' একটি একক নাল মান প্রদান করবে এবং 'এসিংসটোন অরম্পিটি' একটি খালি আইইনুমারেবল ফিরিয়ে দেবে। এটার মত:

public static IEnumerable<T> AsSingletonOrEmpty<T>(this T source)
{
    if (source == null)
    {
        yield break;
    }
    else
    {
        yield return source;
    }
}

public static IEnumerable<T> AsSingleton<T>(this T source)
{
    yield return source;
}

তারপরে, এইগুলি আরও কম-বেশি, আইউনামেবলের 'ফার্স্ট' এবং 'ফার্স্টআরডিফল্ট' এক্সটেনশন পদ্ধতির সাথে সাদৃশ্যপূর্ণ যা কেবল সঠিক মনে করবে।


2

আমি বলার সবচেয়ে সহজ উপায় হ'ল new T[]{item};; এটি করার জন্য কোনও বাক্য গঠন নেই। আমি যে নিকটতম সমতুল্যটি ভাবতে পারি তা হ'ল paramsমূলশব্দ, তবে অবশ্যই এর জন্য আপনাকে পদ্ধতির সংজ্ঞাটি অ্যাক্সেস করতে হবে এবং কেবল অ্যারে দিয়ে ব্যবহারযোগ্য able


2
Enumerable.Range(1,1).Select(_ => {
    //Do some stuff... side effects...
    return item;
});

উপরের কোডটি পছন্দ মতো ব্যবহার করার সময় কার্যকর হয়

var existingOrNewObject = MyData.Where(myCondition)
       .Concat(Enumerable.Range(1,1).Select(_ => {
           //Create my object...
           return item;
       })).Take(1).First();

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


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

আমি এই উত্তরটির বেশিরভাগ অংশ দেখতে পাচ্ছি, আমি যে অংশটি সাড়া দিচ্ছি তা সহ, পরে অন্য কেউ সম্পাদনা করেছিলেন। কিন্তু যদি দ্বিতীয় স্নিপেট এর অভিপ্রায় যদি ডিফল্ট মান প্রদান করা হয় MyData.Where(myCondition)খালি, যা ইতিমধ্যে সম্ভব (এবং সহজ) সাথে DefaultIfEmpty(): var existingOrNewObject = MyData.Where(myCondition).DefaultIfEmpty(defaultValue).First();। আপনি var existingOrNewObject = MyData.FirstOrDefault(myCondition);যদি default(T)কাস্টম মান না চান তবে এটি আরও সরল করা যেতে পারে ।
বেকন

0

আমি পার্টিতে কিছুটা দেরি করেছি তবে যাই হোক আমার পথ ভাগ করে নেব। আমার সমস্যাটি হ'ল আমি আইটেমসোর্স বা একটি ডাব্লুপিএফ ট্রিভিউকে একটি সামগ্রীতে আবদ্ধ করতে চেয়েছিলাম। শ্রেণিবিন্যাসটি দেখতে এরকম দেখাচ্ছে:

প্রকল্প> প্লট (গুলি)> ঘর (গুলি)

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

public class ProjectClass : IEnumerable<ProjectClass>
{
    private readonly SingleItemEnumerator<AufmassProjekt> enumerator;

    ... 

    public IEnumerator<ProjectClass > GetEnumerator() => this.enumerator;

    IEnumerator IEnumerable.GetEnumerator() => this.GetEnumerator();
}

এবং সেই অনুসারে আমার নিজস্ব এনুমুরেটর তৈরি করুন:

public class SingleItemEnumerator : IEnumerator
{
    private bool hasMovedOnce;

    public SingleItemEnumerator(object current)
    {
        this.Current = current;
    }

    public bool MoveNext()
    {
        if (this.hasMovedOnce) return false;
        this.hasMovedOnce = true;
        return true;
    }

    public void Reset()
    { }

    public object Current { get; }
}

public class SingleItemEnumerator<T> : IEnumerator<T>
{
    private bool hasMovedOnce;

    public SingleItemEnumerator(T current)
    {
        this.Current = current;
    }

    public void Dispose() => (this.Current as IDisposable).Dispose();

    public bool MoveNext()
    {
        if (this.hasMovedOnce) return false;
        this.hasMovedOnce = true;
        return true;
    }

    public void Reset()
    { }

    public T Current { get; }

    object IEnumerator.Current => this.Current;
}

এটি সম্ভবত "পরিষ্কার" সমাধান নয় তবে এটি আমার পক্ষে কাজ করেছে।

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

public class SingleItemWrapper : IEnumerable
{
    private readonly SingleItemEnumerator enumerator;

    public SingleItemWrapper(object item)
    {
        this.enumerator = new SingleItemEnumerator(item);
    }

    public object Item => this.enumerator.Current;

    public IEnumerator GetEnumerator() => this.enumerator;
}

public class SingleItemWrapper<T> : IEnumerable<T>
{
    private readonly SingleItemEnumerator<T> enumerator;

    public SingleItemWrapper(T item)
    {
        this.enumerator = new SingleItemEnumerator<T>(item);
    }

    public T Item => this.enumerator.Current;

    public IEnumerator<T> GetEnumerator() => this.enumerator;

    IEnumerator IEnumerable.GetEnumerator() => this.GetEnumerator();
}

যা আমি এরকম ব্যবহার করেছি

TreeView.ItemSource = new SingleItemWrapper(itemToWrap);

সম্পাদনা 2
আমি MoveNext()পদ্ধতিটি দিয়ে একটি ভুল সংশোধন করেছি ।


SingleItemEnumerator<T>বর্গ জ্ঞান করে তোলে, কিন্তু একটি বর্গ একটি "একক আইটেম উপার্জন IEnumerableনিজেই" একক দায়িত্ব নীতি লঙ্ঘন মত মনে হয়। সম্ভবত এটি এটিকে আরও ব্যবহারিক হিসাবে চালিয়ে যায়, তবে আমি এখনও এটি প্রয়োজন মতো মোড়ানো পছন্দ করি।
গ্রো

0

"অগত্যা একটি ভাল সমাধান নয়, তবে এখনও ... একটি সমাধান" বা "বোকা লাইনকিউ ট্রিকস" এর অধীনে দায়ের করা , আপনি এর Enumerable.Empty<>()সাথে একত্রিত করতে পারেন Enumerable.Append<>()...

IEnumerable<string> singleElementEnumerable = Enumerable.Empty<string>().Append("Hello, World!");

... বা Enumerable.Prepend<>()...

IEnumerable<string> singleElementEnumerable = Enumerable.Empty<string>().Prepend("Hello, World!");

.NET ফ্রেমওয়ার্ক 4.7.1 এবং। নেট কোর 1.0 এর পরের দুটি পদ্ধতি উপলব্ধ।

এটি যদি একটি কার্যক্ষম সমাধান হয় তবে যদি কেউ তাদের নিজস্ব লেখার পরিবর্তে বিদ্যমান পদ্ধতিগুলি ব্যবহার করার বিষয়ে সত্যই অভিপ্রায় পোষণ করে থাকে তবে Enumerable.Repeat<>()সমাধানের চেয়ে এটি যদি কম-বেশি পরিষ্কার হয় তবে আমি নির্বিচারে । এটি অবশ্যই দীর্ঘতর কোড (আংশিকরূপে প্যারামিটারের অনুক্রমের পক্ষে সম্ভব হচ্ছে না Empty<>()) এবং এটি দ্বিগুণ পরিমাণে গণক বস্তু তৈরি করে।

এটিকে গোল করে "আপনি কি জানেন যে এই পদ্ধতিগুলি বিদ্যমান?" উত্তর, এর Array.Empty<>()পরিবর্তে প্রতিস্থাপন করা যেতে পারে Enumerable.Empty<>()তবে তর্ক করা শক্ত যে পরিস্থিতি ... আরও উন্নত করে তোলে।


0

আমি সম্প্রতি অন্য পোস্টে একই জিনিসটি জিজ্ঞাসা করেছি ( একটি সিউন পদ্ধতিতে কল করার কোনও উপায় আছে যেখানে একটি একক মানের সাথে একটি আইনিম্যুয়াল <T> প্রয়োজন? ... বেঞ্চমার্কিং সহ )?

আমি চেয়েছিলাম যে লোকেরা এই উত্তরগুলিতে প্রদত্ত 4 টি পদ্ধতির জন্য সেই নতুন পোস্টে দেখানো সংক্ষিপ্ত মানদণ্ডের তুলনাটি দেখতে এখানে থামছে।

দেখে মনে হয় যে new[] { x }পদ্ধতিটিতে আর্গুমেন্টে কেবল লেখাই সংক্ষিপ্ত এবং দ্রুত সমাধান।

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