Foreach loop එකක වත්මන් පුනරාවර්තනයේ දර්ශකය ඔබ ලබා ගන්නේ කෙසේද?


964

පුරෝකථන ලූපයක වර්තමාන පුනරාවර්තනය නියෝජනය කරන අගයක් ලබා ගැනීම සඳහා සී # හි මා හමු නොවූ දුර්ලභ භාෂා නිර්මාණයක් තිබේද (මම මෑතකදී ඉගෙන ගත් කිහිප දෙනා මෙන්, සමහරක් ස්ටැක් පිටාර ගැලීම මත)?

උදාහරණයක් ලෙස, මම දැනට තත්වයන් අනුව මෙවැනි දෙයක් කරමි:

int i = 0;
foreach (Object o in collection)
{
    // ...
    i++;
}

1
foreach වාත්තු නැවත ලබා ගැනීම සාමාන්‍යයෙන් එකතුවක් මත දර්ශක මත පදනම් වූ ප්‍රවේශය භාවිතා කරනවාට වඩා ප්‍රශස්ත නොවේ. බොහෝ අවස්ථාවල එය සමාන වනු ඇත. පුරෝකථනය කිරීමේ පරමාර්ථය වන්නේ ඔබේ කේතය කියවිය හැකි පරිදි සකස් කිරීමයි, නමුත් එය (සාමාන්‍යයෙන්) නිදහස් නොවන, උදාසීන තට්ටුවක් එක් කරයි.
බ්‍රයන්

8
මම ප්රාථමික අරමුණ කියන්නේ foreachනොතකා ඔවුන් සුචිමය (යන්න සියලු එකතු කිරීම සඳහා පොදු ප්රතිඵලයක්ම යාන්ත්රනයක් සම්පාදනය කිරීම List) හෝ නොවේ ( Dictionary).
බ්‍රයන් ගිඩියොන්

2
හායි බ්‍රයන් ගිඩියොන් - නියත වශයෙන්ම එකඟ වන්න (මෙය මීට වසර කිහිපයකට පෙර වූ අතර මම ඒ වන විට අත්දැකීම් අඩුය). කෙසේ වෙතත්, Dictionaryසුචිගත කළ නොහැකි වුවද, පුනරාවර්තනයක් Dictionaryඑය නිශ්චිත අනුපිළිවෙලකට ගමන් කරයි (එනම්, සංඛ්‍යාත්මකව අනුක්‍රමිකව මූලද්‍රව්‍ය ලබා දීමෙන් ගණනය කරන්නෙකු සුචිගත වේ). මෙම අර්ථයෙන් ගත් කල, අප සොයන්නේ එකතුව තුළ ඇති දර්ශකය නොව, ගණනය කිරීම තුළ ඇති වර්තමාන ගණනය කරන ලද මූලද්‍රව්‍යයේ දර්ශකයයි (එනම් අපි පළමු හෝ පස්වන හෝ අවසාන ගණනය කළ මූලද්‍රව්‍යයේ වේවා).
මැට් මිචෙල්

4
foreach විසින් සම්පාදක කේතයේ එක් එක් අරාව ප්‍රවේශයන් පරික්ෂා කිරීම සඳහා සීමාවන් මඟ හැරීමට සම්පාදකයාට ඉඩ දෙයි. දර්ශකයක් සමඟ භාවිතා කිරීම ඔබගේ දර්ශක ප්‍රවේශය ආරක්ෂිත දැයි ධාවන කාලය පරීක්ෂා කරයි.
අයිවෝටොප්ස්

1
නමුත් එය බොරු ය. ඔබ ලූපය තුළ a සඳහා පුනරාවර්තන විචල්‍යය වෙනස් නොකරන්නේ නම්, සම්පාදකයා එහි සීමාවන් මොනවාදැයි දන්නා අතර ඒවා නැවත පරීක්ෂා කිරීමට අවශ්‍ය නොවේ. මෙය එතරම් පොදු අවස්ථාවක් වන අතර ඕනෑම යහපත් සම්පාදකයෙකු එය ක්‍රියාත්මක කරනු ඇත.
ජිම් බෝල්ටර්

Answers:


573

මෙය foreachක්‍රියාත්මක කරනු ලබන එකතු කිරීම් නැවත සිදු කිරීම සඳහා ය IEnumerable. එය මෙය කරන්නේ GetEnumeratorඑකතු කිරීම ඇමතීමෙන් වන අතර එය නැවත ලැබෙනු ඇතEnumerator .

මෙම ගණන් ගන්නා යන්ත්‍රයට ක්‍රමයක් සහ දේපලක් ඇත:

  • MoveNext ()
  • වත්මන්

Currentගණන් ගැනීමේ යන්ත්‍රය දැනට පවතින වස්තුව MoveNextයාවත්කාලීන කරයිCurrent ලබා දෙයි, ඊළඟ වස්තුවට කරයි.

දර්ශකයක සංකල්පය ගණනය කිරීමේ සංකල්පයට විදේශීය වන අතර එය කළ නොහැක.

එම හේතුව නිසා, බොහෝ එකතු කිරීම් දර්ශකයක් සහ ෆෝ ලූප් ඉදිකිරීම භාවිතා කර ගමන් කළ හැකිය.

දේශීය විචල්‍යයක් සමඟ දර්ශකය ලුහුබැඳීමට සාපේක්ෂව මෙම තත්වය තුළ for for loop භාවිතා කිරීමට මම බෙහෙවින් කැමැත්තෙමි.


169
"නිසැකවම, දර්ශක සංකල්පය ගණනය කිරීමේ සංකල්පයට විදේශීය වන අතර එය කළ නොහැක." - ඩේවිඩ් බී සහ බකාහිල්ගේ පිළිතුරු වලින් පැහැදිලි වන පරිදි මෙය විකාරයකි. දර්ශකයක් යනු පරාසයක් ඉක්මවා ගණනය කිරීමක් වන අතර සමාන්තරව කාරණා දෙකක් ගණනය කිරීමට කිසිවෙකුට හැකියාවක් නැත ... එය හරියටම ගණන් කළ හැකි සුචිගත කිරීමේ ස්වරූපයයි.
ජිම් බෝල්ටර්

11
මූලික කේත උදාහරණය:for(var i = 0; i < myList.Count; i ++){System.Diagnostics.Debug.WriteLine(i);}
චැඩ් හෙඩ්කොක්

23
Im ජිම්බෝල්ටර්: මම කියවූ පළමු සබැඳිය එයයි. එය ඔබගේ තනතුරට සහාය වන්නේ කෙසේදැයි මම නොදනිමි. මම පිළිතුරු දෙන විට මිනිසුන් වෙත ඇඩ්-හෝම්ස් සහ බෙදීම් වචන නොකියමි. "විකාර", "අසාමාන්‍ය ව්‍යාකූලතා", "සම්පුර්ණයෙන්ම වැරදි සහ ව්‍යාකූල", "මට උඩු යටිකුරු 37 ක් ලැබුණි" යනාදිය මම උදාහරණයක් ලෙස උපුටා දක්වමි. ඔබගේ 'තර්ක විතර්ක වෙඩිකුන්ඩියම්' සමඟ ඔබ අන් අයට පහර නොදෙන ලෙස ආචාරශීලීව ඉල්ලා සිටීමට කැමැත්තෙමි. ඒ වෙනුවට ස්ටැක් ඕවර්ෆ්ලෝ හි සිටින පුද්ගලයින්ට සහාය දැක්විය හැකි ක්‍රම ගැන සිතා බැලීමට මම ඔබව දිරිමත් කිරීමට කැමැත්තෙමි. මම කියන්නේ ජෝන් ස්කීට් මේ සම්බන්ධයෙන් ආදර්ශ පුරවැසියෙක් බවයි.
ප්‍රෙට්සෙල්

11
ප්‍රෙට්සෙල්: ආදර්ශ පුරවැසියෙකු ලෙස ඔබ ජෝන් ස්කීට් භාවිතා කිරීම වැරදියි, මන්ද මා අත්දැක ඇති පරිදි ඔහු සමඟ එකඟ නොවන අයෙකු ඔහු පහත් කොට සලකනු ඇත. ජිම් බෝල්ටර්: ඔබගේ සමහර අදහස් ඕනෑවට වඩා ආක්‍රමණශීලී වූ අතර ඔබේ අදහස් අඩු කෝපයකින් හා වැඩි අධ්‍යාපනයක් සහිතව ඉදිරිපත් කළ හැකිය.
සන්කැට් 2000

7
Ret ප්‍රෙට්සෙල් ජිම්ගේ අදහස නම්, ඔබට මූලද්‍රව්‍ය පූර්ණ සංඛ්‍යා අනුපිළිවෙලකට සිතියම් ගත කළ හැකි තාක් කල් ඔබට එය සුචිගත කළ හැකිය. පංතිය විසින්ම දර්ශකයක් ගබඩා නොකරන බව කාරණය පසෙකින් පවතී. මීට අමතරව, සම්බන්ධ ලැයිස්තුව බව කරන්නේ ජිම් තත්වය පමණක් ශක්තිමත් නියෝගයක් නැත. ඔබ කළ යුත්තේ එක් එක් මූලද්‍රව්‍යය පිළිවෙලට අංකනය කිරීම පමණි. විශේෂයෙන්, ඔබ ගණන් incrementing විසින් එය කළ හැකි අතර, ඔබ වඩාත් කැපීපෙනේ, හෝ ඔබ එම දිග නිඛිල ලැයිස්තුවක් උත්පාදනය හා පසුව (Python හි දී මෙන් ඔවුන් ZIP හැකි zipකාර්යය).
jpmc26

687

ඉයන් මර්සර් ෆිල් හැක්ගේ බ්ලොග් අඩවියේ මේ හා සමාන විසඳුමක් පළ කළේය :

foreach (var item in Model.Select((value, i) => new { i, value }))
{
    var value = item.value;
    var index = item.i;
}

LINQ හි ​​මෙම අධි බර භාවිතා කිරීමෙන් මෙය ඔබට අයිතමය ( item.value) සහ එහි දර්ශකය ( item.i) ලබා දෙයිSelect :

ශ්‍රිතයේ දෙවන පරාමිතිය [ඇතුළත තෝරන්න] ප්‍රභව මූලද්‍රව්‍යයේ දර්ශකය නිරූපණය කරයි.

මෙම new { i, value }නව නිර්මාණය කරමින් නිර්නාමික වස්තුව .

ValueTupleඔබ C # 7.0 හෝ ඊට පසු භාවිතා කරන්නේ නම් ගොඩවල් වෙන් කිරීම වළක්වා ගත හැකිය :

foreach (var item in Model.Select((value, i) => ( value, i )))
{
    var value = item.value;
    var index = item.i;
}

item.ස්වයංක්‍රීයව විනාශ කිරීම මඟින් ඔබට එය ඉවත් කළ හැකිය :

<ol>
foreach ((MyType value, Int32 i) in Model.Select((value, i) => ( value, i )))
{
    <li id="item_@i">@value</li>
}
</ol>

9
රේසර් අච්චුවක දී මෙම විසඳුම ඉතා අල්පය, එය අච්චුවේ පිළිවෙල සුළුපටු නොවන නිර්මාණ සැළකිල්ලක් වන අතර ගණනය කර ඇති සෑම අයිතමයකම දර්ශකය භාවිතා කිරීමට ඔබට අවශ්‍යය. කෙසේ වෙතත්, 'එතීමෙන්' වස්තු වෙන් කිරීම පූර්ණ සංඛ්‍යාවක් (නොවැළැක්විය හැකි) වැඩි කිරීමට ඉහළින් වියදම (අවකාශය හා වේලාව) එකතු කරන බව මතක තබා ගන්න.
ඩේවිඩ් බුලොක්


24
කණගාටුයි - එය දක්ෂයි, නමුත් එය ඇත්ත වශයෙන්ම කියවීමට වඩා ඉදිරියෙන් දර්ශකයක් නිර්මාණය කර එය එක් එක් ලූපය වැඩි කිරීමට වඩා වැඩි ද?
jbyrd

13
පසුකාලීන C # අනුවාදයන් සමඟ ඔබ ද ටුපල් භාවිතා කරයි, එබැවින් ඔබට මේ වගේ දෙයක් ලැබෙනු ඇත: ආකෘතියෙහි foreach (var (අයිතමය, i). තෝරන්න ((v, i) => (v, i))) ඔබට ඉඩ දෙයි අයිතමය සහ දර්ශකය (i) ටුප් ඩෙකොන්ස්ට්‍රක්ෂන් සමඟ සෘජුවම ෆෝ-ලූප් තුළට පිවිසෙන්න.
හෝක්මන්

6
මෙය හොඳ පිළිතුරක් වන්නේ මන්දැයි යමෙකුට මට පැහැදිලි කළ හැකිද (ලිවීමේදී උඩු යටිකුරු 450 කට වඩා). මට පෙනෙන පරිදි, කවුන්ටරයක් ​​වැඩි කිරීමට වඩා තේරුම් ගැනීම දුෂ්කර ය, එබැවින් නඩත්තු කළ නොහැකි තරම් අඩුය, එය වැඩි මතකයක් භාවිතා කරයි, එය බොහෝ විට මන්දගාමී වේ. මට යමක් මග හැරී තිබේද?
පොහොසත් එන්

207

අවසාන වශයෙන් C # 7 හි foreachලූපයක් තුළ දර්ශකයක් ලබා ගැනීම සඳහා හොඳ වාක්‍ය ඛණ්ඩයක් ඇත (එනම් ටුපල්ස්):

foreach (var (item, index) in collection.WithIndex())
{
    Debug.WriteLine($"{index}: {item}");
}

කුඩා දිගු කිරීමේ ක්‍රමයක් අවශ්‍ය වනු ඇත:

public static IEnumerable<(T item, int index)> WithIndex<T>(this IEnumerable<T> self)       
   => self.Select((item, index) => (item, index)); 

11
මෙම පිළිතුර අවතක්සේරු කර ඇත, ටුපල් තිබීම වඩා පිරිසිදුයි
ටොඩ්

11
ශුන්‍ය එකතු කිරීම් හැසිරවීමට වෙනස් කරන ලදි:public static IEnumerable<(T item, int index)> WithIndex<T>(this IEnumerable<T> self) => self?.Select((item, index) => (item, index)) ?? new List<(T, int)>();
2Toad

1
කදිම එකක්. මම ඇත්තටම මෙම විසඳුමට වඩාත්ම කැමතියි.
ෆ්‍රාන්ස්හබර් 23

1
මෙය හොඳම පිළිතුරයි
w0ns88

3
වෙනත් භාෂාවන්ටEnumerated හුරු පුරුදු පුද්ගලයින්ට වඩාත් හඳුනාගත හැකි ක්‍රමයක් ලෙස හැඳින්වීම ප්‍රයෝජනවත් විය හැකිය (සමහර විට ටුපල් පරාමිතීන්ගේ අනුපිළිවෙලද මාරු කරන්න). නොවන බව පැහැදිලි කෙසේ හෝ නොවේ. WithIndex
FernAndr

118

මේ වගේ දෙයක් කරන්න පුළුවන්:

public static class ForEachExtensions
{
    public static void ForEachWithIndex<T>(this IEnumerable<T> enumerable, Action<T, int> handler)
    {
        int idx = 0;
        foreach (T item in enumerable)
            handler(item, idx++);
    }
}

public class Example
{
    public static void Main()
    {
        string[] values = new[] { "foo", "bar", "baz" };

        values.ForEachWithIndex((item, idx) => Console.WriteLine("{0}: {1}", idx, item));
    }
}

12
එය "සැබවින්ම" ගැටළුව විසඳන්නේ නැත. අදහස හොඳයි, නමුත් එය අතිරේක ගණන් කිරීමේ විචල්‍යය
මගහරින්නේ නැත

අපගේ for loop එක තුළ අපට ආපසු ප්‍රකාශයක් තිබේ නම් මෙය ක්‍රියාත්මක නොවේ, ඔබ ඒ සඳහා "ForEachWithIndex" වෙනස් කළහොත් එය සාමාන්‍ය දෙයක් නොවේ, ලූප සඳහා නිතිපතා ලිවීමට වඩා හොඳය
ශංකර් රාජු

ඔබේ ForEachWithIndex ඇමතුම ලින්ක් තේරීම භාවිතා කරමින් නූලක් සහ දර්ශකයක් ගන්නා ඇමතුමට සමාන වේ:values.Select((item, idx) => { Console.WriteLine("{0}: {1}", idx, item); return item; }).ToList();
user2023861

98

forබොහෝ අවස්ථාවලදී ලූපයක් වඩා හොඳ තේරීමක් යැයි අදහස් දැක්වීමට මම එකඟ නොවෙමි .

foreach යනු ප්‍රයෝජනවත් ඉදිකිරීමක් වන අතර එය ප්‍රතිස්ථාපනය කළ නොහැක for සෑම අවස්ථාවකම ලූපයක් .

උදාහරණයක් ලෙස, ඔබ විසින් ඇති නම් DataReader භාවිතා සියලු වාර්තා හරහා පුඩුවක් foreachඑය ස්වයංක්රීයව ආමන්ත්රණය ඉවත් ක්රමය සහ (එවකට සමීප ස්වයංක්රීයව සම්බන්ධ හැකි) පාඨකයා අවසන් වේ. එබැවින් පා er කයා වැසීමට ඔබට අමතක වුවද සම්බන්ධතා කාන්දු වීම වළක්වන බැවින් මෙය ආරක්ෂිත වේ.

. foreach භාවිතා කිරීමේ පුරුද්ද තුළ.)

Disposeක්‍රමයේ ව්‍යංග ඇමතුම ප්‍රයෝජනවත් වීමට වෙනත් උදාහරණ තිබිය හැකිය .


2
මෙය පෙන්වා දීමට ස්තූතියි. ඒ වෙනුවට සියුම්. ඔබට වැඩි විස්තර pvle.be/2010/05/foreach-statement-calls-dispose-on-ienumerator සහ msdn.microsoft.com/en-us/library/aa664754(VS.71).aspx වෙබ් අඩවියෙන් ලබා ගත හැකිය .
මාර්ක් මුවර්

+1. මම ක්‍රමලේඛකයන්ට වඩා foreachවෙනස් for(හා සමීප while) ආකාරය ගැන විස්තරාත්මකව ලියමින් සිටියෙමි .
අර්සෙනී මෝර්සෙන්කෝ

66

වචනයේ පරිසමාප්ත අර්ථයෙන්ම - අනතුරු ඇඟවීම, කාර්ය සාධනය intදර්ශකය ලුහුබැඳීමට භාවිතා කිරීම තරම් හොඳ නොවනු ඇත . අවම වශයෙන් එය භාවිතා කිරීමට වඩා හොඳයි IndexOf.

එකතුවේ ඇති සෑම අයිතමයක්ම දර්ශකය දන්නා නිර්නාමික වස්තුවක් සමඟ ඔතා ගැනීම සඳහා ඔබ තෝරා ගැනීමේ සුචිගත කිරීමේ භාරය භාවිතා කළ යුතුය. IEnumerable ක්‍රියාත්මක කරන ඕනෑම දෙයකට එරෙහිව මෙය කළ හැකිය.

System.Collections.IEnumerable collection = Enumerable.Range(100, 10);

foreach (var o in collection.OfType<object>().Select((x, i) => new {x, i}))
{
    Console.WriteLine("{0} {1}", o.i, o.x);
}

3
කාස්ට් <T> () වෙනුවට ඔෆ් ටයිප් <T> () භාවිතා කිරීමට ඇති එකම හේතුව නම් ගණන් බැලීමේ සමහර අයිතම පැහැදිලි වාත්තු කිරීමක් අසමත් වුවහොත් පමණි. වස්තුව සඳහා, මෙය කිසි විටෙකත් එසේ නොවේ.
dahlbyk

13
කාස්ට් වෙනුවට ඔෆ් ටයිප් භාවිතා කිරීමට වෙනත් හේතුවක් හැර - නිසැකවම මම කාස්ට් භාවිතා නොකරමි.
ඇමී බී

39

LINQ, C # 7 සහ System.ValueTupleNuGet පැකේජය භාවිතා කිරීමෙන් ඔබට මෙය කළ හැකිය:

foreach (var (value, index) in collection.Select((v, i)=>(v, i))) {
    Console.WriteLine(value + " is at index " + index);
}

ඔබට නිත්‍ය foreachඉදිකිරීමක් භාවිතා කළ හැකි අතර වස්තුවක සාමාජිකයෙකු ලෙස නොව අගය හා දර්ශකය වෙත කෙලින්ම ප්‍රවේශ විය හැකි අතර ක්ෂේත්‍ර දෙකම ලූපයේ විෂය පථයේ පමණක් තබා ගනී. මෙම හේතු නිසා, ඔබට C # 7 සහ භාවිතා කිරීමට හැකි නම් මෙය හොඳම විසඳුම යැයි මම විශ්වාස කරමි System.ValueTuple.


මෙය පරිශීලක 1414213562 ගේ පිළිතුරට වඩා වෙනස් වන්නේ කෙසේද ?
එඩ්වඩ් බ්‍රේ

එඩ්වඩ්බ්‍රේ මම හිතන්නේ එය එසේ නොවේ. මෙම ප්‍රශ්නයට පිළිතුරු රාශියක් ඇත, බොහෝ විට මම එය මග හැරී හෝ එය කරන්නේ කුමක් දැයි නොදැන සිටියේ ඔහු සමහර තර්කනයන් දිගු කිරීමේ ක්‍රමයකට වෙන් කළ බැවිනි.
පවෙල්

1
මෙය වෙනස් වන්නේ .Select LINQ වෙතින් ගොඩනගා ඇති බැවිනි. ඔබට ඔබේම කාර්යයක් ලිවිය යුතු නොවේද? ඔබට VS ස්ථාපනය "System.ValueTuple" තිබිය යුතුය.
ඇන්ටන්

34

@ FlySwat ගේ පිළිතුර භාවිතා කරමින්, මම මෙම විසඳුම ඉදිරිපත් කළෙමි:

//var list = new List<int> { 1, 2, 3, 4, 5, 6 }; // Your sample collection

var listEnumerator = list.GetEnumerator(); // Get enumerator

for (var i = 0; listEnumerator.MoveNext() == true; i++)
{
  int currentItem = listEnumerator.Current; // Get current item.
  //Console.WriteLine("At index {0}, item is {1}", i, currentItem); // Do as you wish with i and  currentItem
}

ඔබ ගණන් ගැනීමේ යන්ත්‍රය භාවිතා GetEnumeratorකර පසුව ලූපයක් භාවිතා කර forලූප් කරයි. කෙසේ වෙතත්, උපක්රමය වන්නේ ලූපයේ තත්වය සෑදීමයිlistEnumerator.MoveNext() == true .

සිට MoveNextඊළඟ අංගය එහි වන අතර, එය අප කෙරෙහි වඩාත් කැපීපෙනේ කිරීමට අවශ්යය අංග දුවද්දී විට පුඩුවක් තත්වය පුඩුවක් නැවතුම් කරවන කරමින්, ප්රවේශ විය හැකි නම්, සැබෑ වූ ගණන් ගැනීමේ ප්රතිලාභ ක්රමය.


10
ListEnumerator.MoveNext () == සත්‍යය සංසන්දනය කිරීමේ අවශ්‍යතාවයක් නොමැත. එය සත්‍ය == සත්‍ය දැයි පරිගණකයෙන් විමසීමට සමාන ය. :) listEnumerator.MoveNext () if} නම් කියන්න
Zesty

9
Est ජෙස්ටි, ඔබ ඇත්තෙන්ම නිවැරදිය. මෙම අවස්ථාවෙහිදී එය එකතු කිරීම වඩා කියවිය හැකි බව මට හැඟුණි, විශේෂයෙන් කොන්දේසියක් ලෙස මම <blahSize හැර වෙනත් කිසිවක් ඇතුළත් කිරීමට පුරුදු නැති පුද්ගලයින් සඳහා.
Gezim

1
ඔබ ගණන් ගන්නා යන්ත්‍රය බැහැර කළ යුතුය.
ඇන්ටෝනන් ලෙජ්සෙක්

1
D එඩ්වඩ්බ්‍රේ ඔබ හරි, එය හොඳ කරුණකි. නමුත් listEnumeratorමෙහි දී කථා කිරීම , එය සාමාන්‍ය ගණනය කරන්නෙකු වන අතර එය ක්‍රියාත්මක කරන IDisposableඅතර බැහැර කළ යුතුය.
ඇන්ටෝනන් ලෙජ්සෙක්

1
@ ඇන්ටෝනන් ලෙජ්ක් List<T>ගණන් කරන්නාට හොඳ ඇල්ලීමක් . එය ක්‍රියාත්මක System.Collections.Generic.IEnumerator<T>වන අතර එය උරුම IDisposableවේ. සඳහා ගණන් ගන්නා List<T>තැනැත්තා කිසිවක් Disposeනොකරන අතර අවසන් කාරකයක් නොමැත, එබැවින් Disposeමෙම නඩුවේ ඇමතීමෙන් කිසිදු බලපෑමක් නැත, නමුත් එය වෙනත් ගණන් කිරීම් සඳහා විය හැකිය.
එඩ්වඩ් බ්‍රේ

28

කවුන්ටර විචල්‍යයක් භාවිතා කිරීමේ කිසිදු වරදක් නැත. ඇත්ත වශයෙන්ම, ඔබ භාවිතා කළත් for, foreach whileනැතහොත්do , කවුන්ටර විචල්‍යයක් කොතැනක හෝ ප්‍රකාශ කර වැඩි කළ යුතුය.

එබැවින් ඔබට සුචිගත කළ සුචිගත එකතුවක් තිබේදැයි ඔබට විශ්වාස නැත්නම් මෙම මෝඩකම භාවිතා කරන්න:

var i = 0;
foreach (var e in collection) {
   // Do stuff with 'e' and 'i'
   i++;
}

වෙන භාවිතය මේ එක නම් ඔබ දැන ඔබගේ බව සුචිමය දර්ශකය ප්රවේශ (ඒ සඳහා දෙනු ලබන එකතුව O (1) වන Arrayසහ සමහරවිට සඳහා List<T>(ලේඛගතකිරීම කියන්නේ නැහැ), නමුත් අවශ්යයෙන්ම අනෙකුත් වර්ග සඳහා (උදාහරණ වශයෙන් LinkedList:))

// Hope the JIT compiler optimises read of the 'Count' property!
for (var i = 0; i < collection.Count; i++) {
   var e = collection[i];
   // Do stuff with 'e' and 'i'
}

IEnumeratorආයාචනා කිරීමෙන් MoveNext()සහ ප්‍රශ්න කිරීමෙන් 'අතින්' ක්‍රියා කිරීම කිසි විටෙකත් අවශ්‍ය නොවිය යුතුය Current- foreachඑම කරදරය ඔබව බේරා ගනී ... ඔබට අයිතම මඟ හැරීමට අවශ්‍ය නම් continue, ලූපයේ ශරීරය භාවිතා කරන්න .

සම්පූර්ණත්වය සඳහා, ඔබේ දර්ශකය සමඟ ඔබ කරමින් සිටි දේ මත පදනම්ව (ඉහත ඉදිකිරීම් මඟින් නම්යශීලී බවක් ලබා දෙයි), ඔබට සමාන්තර ලින්ක් භාවිතා කළ හැකිය:

// First, filter 'e' based on 'i',
// then apply an action to remaining 'e'
collection
    .AsParallel()
    .Where((e,i) => /* filter with e,i */)
    .ForAll(e => { /* use e, but don't modify it */ });

// Using 'e' and 'i', produce a new collection,
// where each element incorporates 'i'
collection
    .AsParallel()
    .Select((e, i) => new MyWrapper(e, i));

අපි AsParallel()ඉහත භාවිතා කරන්නේ , එය දැනටමත් 2014 වන අතර, දේවල් වේගවත් කිරීම සඳහා එම බහු හරයන් හොඳින් භාවිතා කිරීමට අපට අවශ්‍යය. තවද, '' අනුක්රමික 'LINQ සඳහා, ඔබ පමණක් ලබා ForEach()මත දීර්ඝ ක්රමය List<T>හාArray ... හා එය භාවිතා සරල කරන්නේ වඩා ඕනෑම වඩා හොඳ බව පැහැදිලි නැහැ foreachඔබ තවමත් uglier කාරක රීති සඳහා තනි-පිලිතුරු පොටවල් ධාවනය වන බැවින්,.


26

ඔබට මුල් ගණන් ගැනීමේ යන්ත්‍රය දර්ශක තොරතුරු අඩංගු වෙනත් එකක් සමඟ ඔතා තැබිය හැකිය.

foreach (var item in ForEachHelper.WithIndex(collection))
{
    Console.Write("Index=" + item.Index);
    Console.Write(";Value= " + item.Value);
    Console.Write(";IsLast=" + item.IsLast);
    Console.WriteLine();
}

මෙන්න ForEachHelperපන්තිය සඳහා කේතය .

public static class ForEachHelper
{
    public sealed class Item<T>
    {
        public int Index { get; set; }
        public T Value { get; set; }
        public bool IsLast { get; set; }
    }

    public static IEnumerable<Item<T>> WithIndex<T>(IEnumerable<T> enumerable)
    {
        Item<T> item = null;
        foreach (T value in enumerable)
        {
            Item<T> next = new Item<T>();
            next.Index = 0;
            next.Value = value;
            next.IsLast = false;
            if (item != null)
            {
                next.Index = item.Index + 1;
                yield return item;
            }
            item = next;
        }
        if (item != null)
        {
            item.IsLast = true;
            yield return item;
        }            
    }
}

මෙය ඇත්ත වශයෙන්ම අයිතමයේ දර්ශකය ලබා නොදේ. ඒ වෙනුවට, එය ගණනය කළ ලැයිස්තුව තුළ දර්ශකය නැවත ලබා දෙනු ඇත, එය ලැයිස්තුවේ උප ලැයිස්තුවක් පමණක් විය හැකි අතර එමඟින් ඔබට නිවැරදි දත්ත ලබා දෙන්නේ උප ලැයිස්තුව සහ ලැයිස්තුව සමාන ප්‍රමාණයේ වූ විට පමණි. මූලික වශයෙන්, එකතුකිරීමේ වස්තූන් ඇති ඕනෑම වේලාවක ඉල්ලූ ආකාරයේ නොව ඔබේ දර්ශකය වැරදිය.
ලූකස් බී

7
Uc ලූකස්: නැත, නමුත් එය වර්තමාන පුරෝකථන පුනරාවර්තනයේ දර්ශකය නැවත ලබා දෙනු ඇත. ප්‍රශ්නය එයයි.
බ්‍රයන් ගිඩියොන්

21

මෙන්න මම මේ ගැටලුව සඳහා ඉදිරිපත් කළ විසඳුමක්

මුල් කේතය:

int index=0;
foreach (var item in enumerable)
{
    blah(item, index); // some code that depends on the index
    index++;
}

යාවත්කාලීන කළ කේතය

enumerable.ForEach((item, index) => blah(item, index));

ව්‍යාප්ති ක්‍රමය:

    public static IEnumerable<T> ForEach<T>(this IEnumerable<T> enumerable, Action<T, int> action)
    {
        var unit = new Unit(); // unit is a new type from the reactive framework (http://msdn.microsoft.com/en-us/devlabs/ee794896.aspx) to represent a void, since in C# you can't return a void
        enumerable.Select((item, i) => 
            {
                action(item, i);
                return unit;
            }).ToList();

        return pSource;
    }

18

ඇයි පුරෝකථනය කරන්නේ?!

සරලම ආකාරය භාවිතා සඳහා ඒ වෙනුවට foreach ක ඔබ ලැයිස්තුව භාවිතා කරන්නේ නම් :

for (int i = 0 ; i < myList.Count ; i++)
{
    // Do something...
}

නැතහොත් ඔබට foreach භාවිතා කිරීමට අවශ්‍ය නම්:

foreach (string m in myList)
{
     // Do something...
}

එක් එක් ලූපයේ දර්ශකය දැන ගැනීමට ඔබට මෙය භාවිතා කළ හැකිය:

myList.indexOf(m)

9
indexOf විසඳුම අනුපිටපත් සහිත ලැයිස්තුවක් සඳහා වලංගු නොවන අතර එය ඉතා මන්දගාමී වේ.
tymtam

2
වළක්වා ගත යුතු ගැටළුව නම්, ඔබ IEnumerable කිහිප වතාවක් ගමන් කරන ස්ථානයයි, උදා: අයිතම ගණන ලබා ගැනීම සහ ඉන්පසු එක් එක් අයිතමය. උදාහරණයක් ලෙස දත්ත සමුදා විමසුමක ප්‍රති I ලයක් ලෙස IEnumerable වන විට මෙය ඇඟවුම් කරයි.
ඩේවිඩ් ක්ලාක්

2
myList.IndexOf () යනු O (n), එබැවින් ඔබේ ලූපය O (n ^ 2) වනු ඇත.
පැට්‍රික් බියර්ඩ්

16

ඔබේම දර්ශකය එක් කරන්න. එය සරලව තබා ගන්න.

int i = 0;
foreach (var item in Collection)
{
    item.index = i;
    ++i;
}

14

එය වැඩ කිරීමට යන්නේ ලැයිස්තුවක් සඳහා මිස කිසිදු IEnumerable සඳහා නොවේ, නමුත් LINQ හි ​​මෙය තිබේ:

IList<Object> collection = new List<Object> { 
    new Object(), 
    new Object(), 
    new Object(), 
    };

foreach (Object o in collection)
{
    Console.WriteLine(collection.IndexOf(o));
}

Console.ReadLine();

On ජොනතන් මම කිව්වේ නැහැ ඒක නියම පිළිතුරක් කියලා, මම කිව්වේ ඒකෙන් පේනවා එයා ඉල්ලපු දේ කරන්න පුළුවන් කියලා :)

Ra ග්‍රැෆේන් එය වේගවත් වේ යැයි මම අපේක්ෂා නොකරමි - එය ක්‍රියා කරන්නේ කෙසේදැයි මට සම්පුර්ණයෙන්ම විශ්වාස නැත, ගැලපෙන වස්තුවක් සොයා ගැනීම සඳහා සෑම අවස්ථාවකම එය සමස්ත ලැයිස්තුව හරහාම නැවත අවධාරණය කළ හැකිය.

එයින් කියැවෙන්නේ, ලැයිස්තුව මඟින් එක් එක් වස්තුවේ දර්ශකයක් සමඟ ගණන් කළ හැකි බවයි.

ජොනතන්ට වඩා හොඳ අදහසක් ඇති බව පෙනේ, ඔහු විස්තාරනය කරන්නේ නම්?

ඔබ ඉදිරියෙහි සිටින ස්ථානය ගණනය කිරීම වඩා හොඳය, සරල හා වඩා අනුවර්තනය කළ හැකිය.


5
අධික පහත වැටීම ගැන විශ්වාස නැත. නිසැකවම කාර්ය සාධනය මෙය තහනම් කරයි නමුත් ඔබ ප්‍රශ්නයට පිළිතුරු දුන්නා!
මැට් මිචෙල්

4
මෙහි ඇති තවත් ගැටළුවක් නම් එය ක්‍රියාත්මක වන්නේ ලැයිස්තුවේ ඇති අයිතම අද්විතීය නම් පමණි.
CodesInChaos

14

C # 7 අවසානයේ අපට මෙය කිරීමට අලංකාර ක්‍රමයක් ලබා දෙයි:

static class Extensions
{
    public static IEnumerable<(int, T)> Enumerate<T>(
        this IEnumerable<T> input,
        int start = 0
    )
    {
        int i = start;
        foreach (var t in input)
        {
            yield return (i++, t);
        }
    }
}

class Program
{
    static void Main(string[] args)
    {
        var s = new string[]
        {
            "Alpha",
            "Bravo",
            "Charlie",
            "Delta"
        };

        foreach (var (i, t) in s.Enumerate())
        {
            Console.WriteLine($"{i}: {t}");
        }
    }
}

ඔව්, සහ එම්එස් විසින් සීඑල්ආර් / බීසීඑල් දීර් extend කළ යුතුය.
ටොඩ්

9
int index;
foreach (Object o in collection)
{
    index = collection.indexOf(o);
}

එකතු කිරීමේ ආධාරක සඳහා මෙය ක්‍රියා කරයි IList.


69
ගැටළු දෙකක්: 1) මෙය O(n^2)බොහෝ ක්‍රියාත්මක කිරීම් වල IndexOfපවතින O(n)බැවිනි. 2) ලැයිස්තුවේ අනුපිටපත් තිබේ නම් මෙය අසමත් වේ.
CodesInChaos

15
සටහන: O (n ^ 2) යන්නෙන් අදහස් කරන්නේ මෙය විශාල එකතුවක් සඳහා විනාශකාරී ලෙස මන්දගාමී විය හැකි බවයි.
ඕ රූනි

IndexOf ක්‍රමය භාවිතා කිරීම සඳහා විශිෂ්ට නව නිපැයුමක්! Foreach loop හි දර්ශකය (අංකය) ලබා ගැනීමට මා බලාපොරොත්තු වූයේ මෙයයි! බිග් Thx
Mitja Bonca

19
දෙයියනේ, මම හිතනවා ඔයා ඒක පාවිච්චි කළේ නැහැ කියලා! :( එය ඔබට නිර්මාණය කිරීමට අවශ්‍ය නොවූ විචල්‍යය භාවිතා කරයි - ඇත්ත වශයෙන්ම එය n + 1 ints නිර්මාණය කරනු ඇත, මන්ද එම ශ්‍රිතය නැවත පැමිණීම සඳහා එකක් නිර්මාණය කළ යුතු බැවිනි - තවද එම දර්ශක සෙවීම වඩා මන්දගාමී වේ සෑම පියවරකදීම එක් නිඛිල වර්ධක මෙහෙයුමක්. ඇයි මිනිසුන් මෙම පිළිතුරට ඡන්දය නොදෙන්නේ?
කැනහාරි

13
මෙම පිළිතුර භාවිතා නොකරන්න, එක් විවරණයක සඳහන් කර ඇති දෘ truth සත්‍යය මට හමු විය. "ලැයිස්තුවේ අනුපිටපත් තිබේ නම් මෙය අසමත් වේ." !!!
ru ස්

9

මෙය මම කරන්නේ කෙසේද, එය එහි සරල බව / සංක්ෂිප්තය සඳහා කදිමයි, නමුත් ඔබ ලූප් බොඩි තුළ බොහෝ දේ කරන්නේ නම් obj.Value, එය ඉතා ඉක්මනින් පැරණි බවට පත්වේ.

foreach(var obj in collection.Select((item, index) => new { Index = index, Value = item }) {
    string foo = string.Format("Something[{0}] = {1}", obj.Index, obj.Value);
    ...
}

9

මෙම පිළිතුර: සෘජු භාෂා සහාය සඳහා සී # භාෂා කණ්ඩායමට බලපෑම් කරන්න.

ප්‍රමුඛ පිළිතුරෙහි මෙසේ සඳහන් වේ:

නිසැකවම, දර්ශක සංකල්පය ගණනය කිරීමේ සංකල්පයට විදේශීය වන අතර එය කළ නොහැක.

වර්තමාන C # භාෂා අනුවාදය (2020) සම්බන්ධයෙන් මෙය සත්‍යයක් වුවද, මෙය සංකල්පීය CLR / භාෂා සීමාවක් නොවේ, එය කළ හැකිය.

මයික්‍රොසොෆ්ට් සී # භාෂා සංවර්ධන කණ්ඩායමට නව අතුරු මුහුණතක් සඳහා සහය එක් කිරීමෙන් නව සී # භාෂා අංගයක් නිර්මාණය කළ හැකිය IIndexedEnumerable

foreach (var item in collection with var index)
{
    Console.WriteLine("Iteration {0} has value {1}", index, item);
}

//or, building on @user1414213562's answer
foreach (var (item, index) in collection)
{
    Console.WriteLine("Iteration {0} has value {1}", index, item);
}

නම් foreach ()භාවිතා වේ with var indexවර්තමාන වේ, එවිට සම්පාදකවරයා ප්රකාශ කිරීමට අයිතමය එකතු අපේක්ෂා IIndexedEnumerableඅතුරු මුහුණත. අතුරුමුහුණත නොමැති නම්, සම්පාදකයාට දර්ශකය ලුහුබැඳීම සඳහා කේතයට එකතු කරන දර්ශක සංඛ්‍යාත්මක වස්තුවක් සමඟ ප්‍රභවය ඔතා ගත හැකිය.

interface IIndexedEnumerable<T> : IEnumerable<T>
{
    //Not index, because sometimes source IEnumerables are transient
    public long IterationNumber { get; }
}

පසුව, අභ්‍යන්තර දර්ශක ලුහුබැඳීම සඳහා සීඑල්ආර් යාවත්කාලීන කළ හැකි අතර, එය භාවිතා කරනුයේ withමූලපදය නියම කර ඇති අතර ප්‍රභවය කෙලින්ම ක්‍රියාත්මක නොවන්නේ නම් පමණිIIndexedEnumerable

මන්ද:

  • Foreach වඩා හොඳ පෙනුමක් ඇති අතර, ව්‍යාපාරික යෙදුම් වලදී, foreach loops කලාතුරකින් කාර්ය සාධන බාධකයක් වේ
  • Foreach මතකය මත වඩාත් කාර්යක්ෂම විය හැකිය. සෑම පියවරකදීම නව එකතු කිරීම් වලට පරිවර්තනය කිරීම වෙනුවට කාර්යයන් නල මාර්ගයක් තිබීම. අඩු CPU හැඹිලි දෝෂ සහ කසළ එකතු කිරීම් අඩු වූ විට එය තවත් CPU චක්‍ර කිහිපයක් භාවිතා කරන්නේ නම් කවුරුන් සැලකිලිමත් වන්නේද?
  • දර්ශකය ලුහුබැඳීමේ කේතය එක් කිරීමට කෝඩරයට අවශ්‍ය වීම, අලංකාරය නරක් කරයි
  • එය ක්‍රියාත්මක කිරීම තරමක් පහසුය (කරුණාකර මයික්‍රොසොෆ්ට්) පසුගාමී අනුකූල වේ

මෙහි බොහෝ මිනිසුන් Microsoft සේවකයන්ගේ නොහැකි විට, මේ වන නිවැරදි පිළිතුර, ඔබ Microsoft වැනි විශේෂාංග එකතු කිරීමට වරයාට හැකිය. ඔබට දැනටමත් විස්තාරණ ශ්‍රිතයක් සමඟ ඔබේම අනුකාරකයක් සාදා ටුපල් භාවිතා කළ හැකිය, නමුත් විස්තාරණ ක්‍රියාකාරිත්වය වළක්වා ගැනීම සඳහා මයික්‍රොසොෆ්ට් හට සින්ටැක්ටික් සීනි ඉසිය හැක.


රැඳී සිටින්න, එබැවින් මෙම භාෂා අංගය දැනටමත් තිබේද, නැතහොත් එය අනාගතය සඳහා යෝජනා කර තිබේද?
පවෙල්

1
APavel මම පැහැදිලිව පෙනෙන පරිදි පිළිතුර යාවත්කාලීන කළෙමි. මෙම පිළිතුර සපයනු ලැබුවේ "නිසැකවම, දර්ශකයක සංකල්පය ගණනය කිරීමේ සංකල්පයට විදේශීය වන අතර එය කළ නොහැකි ය."
ටොඩ්

6

එකතුව ලැයිස්තුවක් නම්, ඔබට List.IndexOf භාවිතා කළ හැකිය:

foreach (Object o in collection)
{
    // ...
    @collection.IndexOf(o)
}

13
දැන් ඇල්ගොරිතම O (n ^ 2) (වඩා නරක නොවේ නම්) වේ. මෙය භාවිතා කිරීමට පෙර මම ඉතා ප්‍රවේශමෙන් සිතමි . එය ද ruc ලදායී පිළිතුරේ අනුපිටපතකි
බ්‍රැඩ්ලි ඩොට්නෙට්

1
@BradleyDotNET හරියටම හරි, මෙම අනුවාදය භාවිතා නොකරන්න.
ඔස්කාර්

1
මේ ගැන සැලකිලිමත් වන්න! ඔබේ ලැයිස්තුවේ අනුපිටපත් අයිතමයක් තිබේ නම්, එය පළමු එකේ ස්ථානය ලබා ගනී!
සොන්ජා

5

continueමේ වගේ ආරක්ෂිත ඉදිකිරීම් සඳහා මූලික වචන භාවිතා කිරීම වඩා හොඳය

int i=-1;
foreach (Object o in collection)
{
    ++i;
    //...
    continue; //<--- safe to call, index will be increased
    //...
}

5

ඔබේ ලූපය මේ ආකාරයෙන් ලිවිය හැකිය:

var s = "ABCDEFG";
foreach (var item in s.GetEnumeratorWithIndex())
{
    System.Console.WriteLine("Character: {0}, Position: {1}", item.Value, item.Index);
}

පහත දැක්වෙන ව්‍යුහය හා ව්‍යාප්ති ක්‍රමය එකතු කිරීමෙන් පසුව.

ව්‍යුහාත්මක හා ව්‍යාප්ති ක්‍රමය ගණන් කළ හැකි ය. ක්‍රියාකාරීත්වය තෝරන්න.

public struct ValueWithIndex<T>
{
    public readonly T Value;
    public readonly int Index;

    public ValueWithIndex(T value, int index)
    {
        this.Value = value;
        this.Index = index;
    }

    public static ValueWithIndex<T> Create(T value, int index)
    {
        return new ValueWithIndex<T>(value, index);
    }
}

public static class ExtensionMethods
{
    public static IEnumerable<ValueWithIndex<T>> GetEnumeratorWithIndex<T>(this IEnumerable<T> enumerable)
    {
        return enumerable.Select(ValueWithIndex<T>.Create);
    }
}

3

මෙම ගැටළුව සඳහා මගේ විසඳුම දිගු කිරීමේ ක්‍රමයකි WithIndex(),

http://code.google.com/p/ub-dotnet-utilities/source/browse/trunk/Src/Utilities/Extensions/EnumerableExtensions.cs

එය මෙන් භාවිතා කරන්න

var list = new List<int> { 1, 2, 3, 4, 5, 6 };    

var odd = list.WithIndex().Where(i => (i.Item & 1) == 1);
CollectionAssert.AreEqual(new[] { 0, 2, 4 }, odd.Select(i => i.Index));
CollectionAssert.AreEqual(new[] { 1, 3, 5 }, odd.Select(i => i.Item));

මම struct(දර්ශකය, අයිතමය) යුගල සඳහා භාවිතා කරමි .
කෝඩ්ස්ඉන්චෝස්

3

උනන්දුව සඳහා, ෆිල් හැක් මේ සඳහා උදාහරණයක් ලියා ඇත්තේ රේසර් සැකිලි නියෝජිතයෙකුගේ ( http://haacked.com/archive/2011/04/14/a-better-razor-foreach-loop.aspx )

Ite ලදායී ලෙස ඔහු දීර් it කිරීමේ ක්‍රමයක් ලියන අතර එය පුනරාවර්තනය "ඉටරේටඩ් අයිටම්" පන්තියක ඔතා ඇත (පහත බලන්න) දර්ශකයට මෙන්ම පුනරාවර්තනයේදී මූලද්‍රව්‍යයට ප්‍රවේශ වීමට ඉඩ සලසයි.

public class IndexedItem<TModel> {
  public IndexedItem(int index, TModel item) {
    Index = index;
    Item = item;
  }

  public int Index { get; private set; }
  public TModel Item { get; private set; }
}

කෙසේ වෙතත්, ඔබ තනි මෙහෙයුමක් කරන්නේ නම් (එනම් ලැම්බඩා ලෙස සැපයිය හැකි) රේසර් නොවන පරිසරයක මෙය හොඳ වනු ඇති අතර එය රේසර් නොවන සන්දර්භයන් සඳහා / foreach සින්ටැක්ස් වෙනුවට replace න ආදේශකයක් නොවනු ඇත. .


3

මෙය තරමක් කාර්යක්ෂම විය යුතු යැයි මම නොසිතමි, නමුත් එය ක්‍රියාත්මක වේ:

@foreach (var banner in Model.MainBanners) {
    @Model.MainBanners.IndexOf(banner)
}

3

මම මෙය ලින්ක්පැඩ් හි ගොඩනගා ඇත :

var listOfNames = new List<string>(){"John","Steve","Anna","Chris"};

var listCount = listOfNames.Count;

var NamesWithCommas = string.Empty;

foreach (var element in listOfNames)
{
    NamesWithCommas += element;
    if(listOfNames.IndexOf(element) != listCount -1)
    {
        NamesWithCommas += ", ";
    }
}

NamesWithCommas.Dump();  //LINQPad method to write to console.

ඔබට ද භාවිතා කළ හැකිය string.join:

var joinResult = string.Join(",", listOfNames);

ඔබට c # හි string.join ද භාවිතා කළ හැකිය. උදාහරණයක් ලෙස: var joinResult = string.Join (",", listOfNames); '
වොරන් ලාෆ්‍රන්ස්

1
මේ O (n * n) දේ කුමක්දැයි යමෙකුට මට පැහැදිලි කළ හැකිද?
ඇක්සෙල්

X ඇක්සෙල් එහි මූලික වශයෙන් අදහස් කරන්නේ ප්‍රති result ලය ගණනය කිරීමට අවශ්‍ය මෙහෙයුම් ප්‍රමාණය හතර ගුණයකින් වැඩි වන බවයි, එනම් nඅයිතම තිබේ නම් මෙහෙයුම් n * nහෝ nවර්ගීකරණය වේ. en.wikipedia.org/wiki/…
රිචඩ් හැන්සල්

2

Foreach loop එකක වර්තමාන පුනරාවර්තනයේ වටිනාකම ලබා ගැනීමට ක්‍රමයක් ඇතැයි මම විශ්වාස නොකරමි. ඔබම ගණනය කිරීම හොඳම ක්‍රමය බව පෙනේ.

මම අහන්නම්, ඇයි ඔයාට දැනගන්න ඕන?

ඔබ බොහෝ දුරට කාරණා තුනෙන් එකක් කරන බව පෙනේ:

1) එකතුවෙන් වස්තුව ලබා ගැනීම, නමුත් මේ අවස්ථාවේ දී ඔබට එය දැනටමත් තිබේ.

2) පසුකාලීන සැකසුම් සඳහා වස්තු ගණනය කිරීම ... එකතුකිරීම් වල ඔබට භාවිතා කළ හැකි ගණන් කිරීමේ දේපලක් ඇත.

3) වස්තුවක් එහි ඇති අනුපිළිවෙල මත පදනම්ව ලූපයක් සැකසීම ... ඔබ එකතු කිරීමට වස්තුව එකතු කළ විට එය පහසුවෙන් සැකසිය හැකිය.


4) මා කිහිප වතාවක් පහර දුන් නඩුව පළමු හෝ අවසාන මුරපදයේදී කළ යුතු වෙනස් දෙයකි - ඔබ මුද්‍රණය කිරීමට යන වස්තු ලැයිස්තුවක් කියන්න, ඔබට අයිතම අතර කොමාව අවශ්‍ය නමුත් අවසාන අයිතමයෙන් පසුව නොවේ.
ලොරන් පෙක්ටෙල්

2

ඔබේ එකතුවට කිසියම් ක්‍රමයක් හරහා වස්තුවේ දර්ශකය ආපසු ලබා දිය නොහැකි නම්, එකම ක්‍රමය ඔබේ උදාහරණයේ මෙන් කවුන්ටරයක් ​​භාවිතා කිරීමයි.

කෙසේ වෙතත්, දර්ශක සමඟ වැඩ කරන විට, ගැටලුවට ඇති එකම සාධාරණ පිළිතුර වන්නේ ලූපයක් භාවිතා කිරීමයි. වෙනත් ඕනෑම දෙයක් කේත සංකීර්ණතාව හඳුන්වා දෙයි, කාලය සහ අවකාශයේ සංකීර්ණතාව සඳහන් නොකරයි.


2

මේ වගේ දෙයක් ගැන කොහොමද? MyEnumerable හිස් නම් myDelimitedString අහෝසි විය හැකි බව සලකන්න.

IEnumerator enumerator = myEnumerable.GetEnumerator();
string myDelimitedString;
string current = null;

if( enumerator.MoveNext() )
    current = (string)enumerator.Current;

while( null != current)
{
    current = (string)enumerator.Current; }

    myDelimitedString += current;

    if( enumerator.MoveNext() )
        myDelimitedString += DELIMITER;
    else
        break;
}

මෙහි විවිධ ගැටළු. අ) අමතර වරහන. B) නූල් කොන්කට් + = ලූප පුනරාවර්තනයකට.
enorl76

2

මට මේ ගැටලුව තිබුනි, නමුත් මගේ නඩුවේ ගැටලුව ගැන සිතීම අපේක්ෂිත විසඳුමට සම්බන්ධ නොවන හොඳම විසඳුම ලබා දුන්නේය.

එය තරමක් පොදු අවස්ථාවක් විය හැකිය, මූලික වශයෙන්, මම එක් ප්‍රභව ලැයිස්තුවකින් කියවා ඒවා පදනම් කරගත් ගමනාන්ත ලැයිස්තුවක් මත වස්තු නිර්මාණය කරමි, කෙසේ වෙතත්, ප්‍රභව අයිතම පළමුව වලංගු ද යන්න පරීක්ෂා කර බලා ඕනෑම පේළියක් ආපසු ලබා දීමට මට අවශ්‍යය දෝෂයකි. බැලූ බැල්මට, වත්මන් දේපලෙහි වස්තුව ගණනය කරන්නාට දර්ශකය ලබා ගැනීමට මට අවශ්‍යය, කෙසේ වෙතත්, මම මෙම මූලද්‍රව්‍ය පිටපත් කරන බැවින්, වත්මන් ගමනාන්තයෙන් කෙසේ හෝ වත්මන් දර්ශකය ව්‍යංගයෙන් දනිමි. නිසැකවම එය ඔබගේ ගමනාන්ත වස්තුව මත රඳා පවතී, නමුත් මට එය ලැයිස්තුවක් වූ අතර බොහෝ දුරට එය ICollection ක්‍රියාත්මක කරනු ඇත.

එනම්

var destinationList = new List<someObject>();
foreach (var item in itemList)
{
  var stringArray = item.Split(new char[] { ';', ',' }, StringSplitOptions.RemoveEmptyEntries);

  if (stringArray.Length != 2)
  {
    //use the destinationList Count property to give us the index into the stringArray list
    throw new Exception("Item at row " + (destinationList.Count + 1) + " has a problem.");
  }
  else
  {
    destinationList.Add(new someObject() { Prop1 = stringArray[0], Prop2 = stringArray[1]});
  }
}

සෑම විටම අදාළ නොවේ, නමුත් බොහෝ විට සඳහන් කිරීම වටී යැයි මම සිතමි.

කෙසේ වෙතත්, කාරණය වන්නේ සමහර විට ඔබ සතුව ඇති තර්කනයේ පැහැදිලි නොවන විසඳුමක් දැනටමත් තිබීමයි ...


2

ප්‍රශ්නය මත පදනම්ව ඔබ දර්ශක තොරතුරු සමඟ කුමක් කිරීමට උත්සාහ කරන්නේ දැයි මට විශ්වාස නැත. කෙසේ වෙතත්, C # හි, ඔබට සාමාන්‍යයෙන් IEnumerable අනුවර්තනය කළ හැකිය. ඔබට අවශ්‍ය ඕනෑම දෙයකින් දර්ශකය ලබා ගැනීම සඳහා තෝරා ගැනීමේ ක්‍රමය. උදාහරණයක් ලෙස, වටිනාකමක් අමුතුද නැතිනම් පවා මම මේ වගේ දෙයක් භාවිතා කළ හැකිය.

string[] names = { "one", "two", "three" };
var oddOrEvenByName = names
    .Select((name, index) => new KeyValuePair<string, int>(name, index % 2))
    .ToDictionary(kvp => kvp.Key, kvp => kvp.Value);

ලැයිස්තුවේ ඇති අයිතමය අමුතු (1) හෝ (0) පවා නම් කිරීමෙන් ඔබට ශබ්ද කෝෂයක් ලබා දෙනු ඇත.

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.