2014-06-10 6 views
5

शीर्षक से पता चलता है कि मुझे पहले से ही एक विचार है कि क्या हो रहा है, लेकिन मैं इसे समझा नहीं सकता। मैंने प्रत्येक "कॉलम" द्वारा गतिशील रूप से List<string[]> ऑर्डर करने का प्रयास किया है, जो पहले से शुरू होता है और सभी सरणी के न्यूनतम Length के साथ समाप्त होता है।फॉर-लूप और LINQ के स्थगित निष्पादन अच्छी तरह से नहीं खेलते हैं

तो इस नमूने में यह 2 है, क्योंकि पिछले string[] केवल दो तत्व हैं:

List<string[]> someValues = new List<string[]>(); 
someValues.Add(new[] { "c", "3", "b" }); 
someValues.Add(new[] { "a", "1", "d" }); 
someValues.Add(new[] { "d", "4", "a" }); 
someValues.Add(new[] { "b", "2" }); 

अब मैं पहले और दूसरे कॉलम के आधार पर सभी ऑर्डर करने के लिए कोशिश की है। मैं इस तरह से स्थिर यह कर सकता है:

someValues = someValues 
    .OrderBy(t => t[0]) 
    .ThenBy(t => t[1]) 
    .ToList(); 

लेकिन अगर मैं "कॉलम" की संख्या पता नहीं है मैं इस पाश इस्तेमाल कर सकते हैं (यह है कि मैं क्या सोचा है):

int minDim = someValues.Min(t => t.GetLength(0)); // 2 
IOrderedEnumerable<string[]> orderedValues = someValues.OrderBy(t => t[0]); 
for (int i = 1; i < minDim; i++) 
{ 
    orderedValues = orderedValues.ThenBy(t => t[i]); 
} 
someValues = orderedValues.ToList(); // IndexOutOfRangeException 

लेकिन उस काम नहीं करता है, यह अंतिम पंक्ति पर IndexOutOfRangeException के साथ विफल रहता है। डीबगर मुझे बताता है कि i उस समय 2 है, इसलिए फॉर-लूप स्थिति को अनदेखा किया जा रहा है, i पहले से ही == minDim है।

ऐसा क्यों है? इसके लिए सही तरीका क्या है?

उत्तर

7

यह एक ही समस्या बहुत से लोग foreach के साथ किया था के रूप में है लूप पूर्व सी # 5.

orderedValues = orderedValues.ThenBy(t => t[i]); 

i का मूल्य:

एक समाधान पाश के भीतर एक बंद करने चर बनाने के लिए है तब तक मूल्यांकन नहीं किया जाएगा जब तक कि आप .ToList() पर कॉल न करें, जिस बिंदु पर यह 2 है क्योंकि यह लूप के बाहर निकलने की स्थिति है।

आप के लिए लूप के अंदर एक नया स्थानीय चर परिचय इसे ठीक करने के कर सकते हैं:

for (int i = 1; i < minDim; i++) 
{ 
    var tmp = i; 
    orderedValues = orderedValues.ThenBy(t => t[tmp]); 
} 

अधिक जानकारी के लिए आप एरिक Lippert के ब्लॉग पोस्ट के बारे में Closing over the loop variable considered harmful पर एक नज़र ले सकता है।

+0

_ "लूप के लिए" नहीं बदला जाएगा। "_ तो अगर मैं अभी भी .NET 4 का उपयोग कर रहा हूं, तो यह समस्या उन लोगों से भी संबंधित है जो पहले से ही सी # 5 का उपयोग कर रहे हैं। –

+0

हां, यह सी # 5 में फोरच-लूप के ब्रेकिंग चेंज के साथ समस्याओं में से एक है। एक तरह से वे अब फॉर-लूप से अलग व्यवहार करते हैं। – Dirk

6

यह शायद हो रहा है क्योंकि i का मूल्य पाश के भीतर बंद नहीं है - जब पाश बाहर निकलता है, i2 और तोt[i] आस्थगित निष्पादन की वजह से मूल्यांकन किया जाएगा के एक मूल्य होगा।

int minDim = someValues.Min(t => t.GetLength(0)); // 2 
IOrderedEnumerable<string[]> orderedValues = someValues.OrderBy(t => t[0]); 
for (int i = 1; i < minDim; i++) 
{ 
    var x = i; 
    orderedValues = orderedValues.ThenBy(t => t[x]); 
} 
someValues = orderedValues.ToList(); 
+0

धन्यवाद, मैंने डिर्क स्वीकार कर लिया है क्योंकि उन्होंने 'foreach loops pre C# 5' और (अब) ई लिपर्ट के ब्लॉग का लिंक बताया है जो सभी बताता है। –

+1

@TimSchmelter मेला पर्याप्त - खुशी है कि आप इसे काम कर रहे हैं। –

संबंधित मुद्दे