আপনি ব্যবহার করছেন yield return
। এটি করার সময়, সংকলকটি আপনার পদ্ধতিটিকে এমন একটি ফাংশনে পুনর্লিখন করবে যা একটি উত্পাদিত শ্রেণি ফেরত দেয় যা একটি রাষ্ট্রের মেশিন প্রয়োগ করে।
বিস্তৃতভাবে বলতে গেলে, এটি স্থানীয়দের সেই শ্রেণীর ক্ষেত্রগুলিতে পুনর্লিখন করে এবং yield return
নির্দেশগুলির মধ্যে আপনার অ্যালগরিদমের প্রতিটি অংশই একটি রাজ্যে পরিণত হয়। সংকলনের পরে এই পদ্ধতিটি কী হয়ে যায় আপনি একটি ডিকম্পিলার দিয়ে পরীক্ষা করতে পারেন (স্মার্ট ডিসকোপিলেশনটি যা উত্পাদন করবে তা বন্ধ করে দেওয়ার বিষয়টি নিশ্চিত করুন yield return
)।
তবে নীচের লাইনটি হল: আপনি পুনরাবৃত্তি শুরু না করা পর্যন্ত আপনার পদ্ধতির কোডটি কার্যকর করা হবে না।
পূর্বশর্তগুলি পরীক্ষা করার স্বাভাবিক উপায় হ'ল আপনার পদ্ধতিটি দুটি ভাগে ভাগ করা:
public static IEnumerable<int> AllIndexesOf(this string str, string searchText)
{
if (str == null)
throw new ArgumentNullException("str");
if (searchText == null)
throw new ArgumentNullException("searchText");
return AllIndexesOfCore(str, searchText);
}
private static IEnumerable<int> AllIndexesOfCore(string str, string searchText)
{
for (int index = 0; ; index += searchText.Length)
{
index = str.IndexOf(searchText, index);
if (index == -1)
break;
yield return index;
}
}
এটি কাজ করে কারণ প্রথম পদ্ধতিটি আপনার প্রত্যাশার মতোই আচরণ করবে (তাত্ক্ষণিক কার্যকরকরণ), এবং দ্বিতীয় পদ্ধতি দ্বারা প্রয়োগকৃত রাষ্ট্রীয় যন্ত্রটি ফিরিয়ে দেবে।
মনে রাখবেন যে আপনার str
জন্য প্যারামিটারটিও পরীক্ষা করা উচিত null
, কারণ এক্সটেনশন পদ্ধতিগুলি মানগুলিতে কল করা যেতে পারে null
, কারণ তারা কেবল সিনট্যাকটিক চিনি।
আপনার কোডটিতে সংকলকটি কী করে সে সম্পর্কে যদি আপনি কৌতূহল থেকে থাকেন তবে আপনার পদ্ধতিটি এখানে শট কম্পাইলার-জেনারেট কোড বিকল্পটি বিকল্পটি ব্যবহার করে ডটপিকের সাথে সংক্ষেপিত ।
public static IEnumerable<int> AllIndexesOf(this string str, string searchText)
{
Test.<AllIndexesOf>d__0 allIndexesOfD0 = new Test.<AllIndexesOf>d__0(-2);
allIndexesOfD0.<>3__str = str;
allIndexesOfD0.<>3__searchText = searchText;
return (IEnumerable<int>) allIndexesOfD0;
}
[CompilerGenerated]
private sealed class <AllIndexesOf>d__0 : IEnumerable<int>, IEnumerable, IEnumerator<int>, IEnumerator, IDisposable
{
private int <>2__current;
private int <>1__state;
private int <>l__initialThreadId;
public string str;
public string <>3__str;
public string searchText;
public string <>3__searchText;
public int <index>5__1;
int IEnumerator<int>.Current
{
[DebuggerHidden] get
{
return this.<>2__current;
}
}
object IEnumerator.Current
{
[DebuggerHidden] get
{
return (object) this.<>2__current;
}
}
[DebuggerHidden]
public <AllIndexesOf>d__0(int <>1__state)
{
base..ctor();
this.<>1__state = param0;
this.<>l__initialThreadId = Environment.CurrentManagedThreadId;
}
[DebuggerHidden]
IEnumerator<int> IEnumerable<int>.GetEnumerator()
{
Test.<AllIndexesOf>d__0 allIndexesOfD0;
if (Environment.CurrentManagedThreadId == this.<>l__initialThreadId && this.<>1__state == -2)
{
this.<>1__state = 0;
allIndexesOfD0 = this;
}
else
allIndexesOfD0 = new Test.<AllIndexesOf>d__0(0);
allIndexesOfD0.str = this.<>3__str;
allIndexesOfD0.searchText = this.<>3__searchText;
return (IEnumerator<int>) allIndexesOfD0;
}
[DebuggerHidden]
IEnumerator IEnumerable.GetEnumerator()
{
return (IEnumerator) this.System.Collections.Generic.IEnumerable<System.Int32>.GetEnumerator();
}
bool IEnumerator.MoveNext()
{
switch (this.<>1__state)
{
case 0:
this.<>1__state = -1;
if (this.searchText == null)
throw new ArgumentNullException("searchText");
this.<index>5__1 = 0;
break;
case 1:
this.<>1__state = -1;
this.<index>5__1 += this.searchText.Length;
break;
default:
return false;
}
this.<index>5__1 = this.str.IndexOf(this.searchText, this.<index>5__1);
if (this.<index>5__1 != -1)
{
this.<>2__current = this.<index>5__1;
this.<>1__state = 1;
return true;
}
goto default;
}
[DebuggerHidden]
void IEnumerator.Reset()
{
throw new NotSupportedException();
}
void IDisposable.Dispose()
{
}
}
এটি অবৈধ সি # কোড, কারণ সংকলকটি ভাষাকে অনুমতি দেয় না এমন কাজ করার অনুমতি দেওয়া হয় তবে আইএল-এ বৈধ - উদাহরণস্বরূপ ভেরিয়েবলের নামকরণ এমনভাবে করা যাতে আপনি নাম সংঘর্ষ এড়াতে পারবেন না।
তবে আপনি দেখতে পাচ্ছেন, AllIndexesOf
কেবলমাত্র একটি অবজেক্ট তৈরি করে এবং ফেরত দেয়, যার নির্মাতা কেবল কিছু স্থিতি শুরু করে। GetEnumerator
কেবল বস্তুটি অনুলিপি করে। আসল কাজটি করা হয় যখন আপনি গণনা শুরু করেন ( MoveNext
পদ্ধতিটি কল করে )।