2012-10-05 14 views
20

वहाँ एक कस्टम प्रकार comparer साथ किसी भी Linq अभिव्यक्ति के दो स्वरूप हैं:Linq वाक्यविन्यास <T>

स्वरूप 1

var query = 
    source 
    .Select(x => new { x.someProperty, x.otherProperty }) 
    .OrderBy(x => x, new myComparer()); 

स्वरूप 2

var query = 
    from x in source 
    orderby x // comparer expression goes here? 
    select new { x.someProperty, x.otherProperty }; 

प्रश्न :
दूसरे फॉर्म में ऑर्डर द्वारा अभिव्यक्ति के लिए वाक्यविन्यास क्या है टी?

नहीं प्रश्न:
के रूप में पहली प्रारूप में दिखाया गया है एक कस्टम comparer का उपयोग कैसे करें।

बोनस क्रेडिट:
वहाँ ऊपर सूचीबद्ध दो Linq प्रारूपों के लिए वास्तविक, औपचारिक नाम हैं?

उत्तर

19

क्या दूसरे प्रारूप में अभिव्यक्ति द्वारा आदेश के लिए वाक्य रचना है?

यह अस्तित्व में नहीं है। orderby clause documentation से:

आप एक कस्टम तुलनाकर्ता भी निर्दिष्ट कर सकते हैं। हालांकि, यह केवल विधि-आधारित सिंटैक्स का उपयोग करके उपलब्ध है।


कैसे पहले प्रारूप में एक कस्टम comparer उपयोग करने के लिए।

आपने इसे सही ढंग से लिखा है। जैसा कि आपने लिखा है, आप IComparer<T> पास कर सकते हैं।


ऊपर सूचीबद्ध दो Linq प्रारूपों के लिए वास्तविक, औपचारिक नाम हैं?

स्वरूप 1 "विधि आधारित सिंटेक्स" (from previous link) कहा जाता है, और स्वरूप 2 "क्वेरी अभिव्यक्ति सिंटेक्स" (here से) है।

+1

गुणवत्ता linq लिंक! यद्यपि विधि आधारित सिंटैक्स में ऑर्डर-सिंटैक्स के बारे में बयान वास्तव में उत्तर का हिस्सा नहीं माना जाता था। :) –

+1

@SteveKonves मैंने इसे अभी भी शामिल किया है। आप आसानी से अनदेखा कर सकते हैं;) –

2

पहले प्रारूप में दिखाए गए कस्टम तुलनाकर्ता का उपयोग कैसे करें।

आप उस प्रारूप में एक कस्टम तुलनाकर्ता का उपयोग नहीं कर सकते हैं।

क्या ऊपर सूचीबद्ध दो लिंक प्रारूपों के लिए वास्तविक, औपचारिक नाम हैं?

स्वरूप 1, स्वरूप 2 "क्वेरी सिंटैक्स" है, विधि वाक्य रचना है

2

प्रश्न: क्वेरी सिंटैक्स में संभव नहीं

यही है, क्योंकि वहाँ कोई भार के हैं।

नहीं प्रश्न:

आप केवल अगर आप वस्तुओं की तुलना करने के लिए प्रतिबिंब का उपयोग गुमनाम प्रकार के साथ एक comparer उपयोग कर सकते हैं, यह तुलना करने के लिए एक टाइप किया कार्यान्वयन उपयोग करने के लिए बेहतर है।

var query = 
    source 
    .Select(x => new Tuple<string, int>(x.someProperty, x.otherProperty)) 
    .OrderBy(x => x, new MyComparer()); 

public class MyComparer : IComparer<Tuple<string, int>> 
{ 
    public int Compare(Tuple<string, int> x, Tuple<string, int> y) 
    { 
    return x.Item1.CompareTo(y.Item1); 
    } 
} 

बोनस क्रेडिट:

आप एक टाइप कार्यान्वयन के लिए नहीं करना चाहते हैं तो आप एक Tuple उपयोग कर सकते हैं

  • क्वेरी सिंटैक्स या समझ सिंटेक्स
  • विधि वाक्य रचना या एक्सटेंशन विधि सिंटेक्स
2

यह आवश्यक रूप से मूल प्रश्न का उत्तर नहीं दे रहा है, लेकिन यह कुछ हद तक उल्लिखित संभावनाओं को बढ़ाता है। अगर मैं इसी तरह की समस्या में आ जाता हूं तो मैं इसे पोस्ट कर रहा हूं। यहां पोस्ट किया गया समाधान विकल्प द्वारा एक सामान्य आदेश की रूपरेखा देता है जो अन्य मामलों में उपयोगी हो सकता है। इस उदाहरण में, मैं विभिन्न गुणों से एक फ़ाइल सूची सॉर्ट करना चाहता था।

/// <summary> 
/// Used to create custom comparers on the fly 
/// </summary> 
/// <typeparam name="T"></typeparam> 
public class GenericCompare<T> : IComparer<T> 
{ 
    // Function use to perform the compare 
    private Func<T, T, int> ComparerFunction { set; get; } 

    // Constructor 
    public GenericCompare(Func<T, T, int> comparerFunction) 
    { 
     ComparerFunction = comparerFunction; 
    } 

    // Execute the compare 
    public int Compare(T x, T y) 
    { 

     if (x == null || y == null) 
     { 
      // These 3 are bell and whistles to handle cases where one of the two is null, to sort to top or bottom respectivly 
      if (y == null && x == null) { return 0; } 
      if (y == null) { return 1; } 
      if (x == null) { return -1; } 
     } 

     try 
     { 
      // Do the actual compare 
      return ComparerFunction(x, y); 
     } 
     catch (Exception ex) 
     { 
      // But muffle any errors 
      System.Diagnostics.Debug.WriteLine(ex); 
     } 

     // Oh crud, we shouldn't be here, but just in case we got an exception. 
     return 0; 
    } 
} 
कार्यान्वयन में

फिर ...

 GenericCompare<FileInfo> DefaultComparer; 

     if (SortOrder == SORT_FOLDER_FILE) 
     { 
      DefaultComparer = new GenericCompare<FileInfo>((fr1, fr2) => 
      { 
       return fr1.FullName.ToLower().CompareTo(fr2.FullName.ToLower()); 
      }); 
     } 
     else if (SortOrder == SORT_SIZE_ASC) 
     { 
      DefaultComparer = new GenericCompare<FileInfo>((fr1, fr2) => 
      { 
       return fr1.Length.CompareTo(fr2.Length); 
      }); 
     } 
     else if (SortOrder == SORT_SIZE_DESC) 
     { 
      DefaultComparer = new GenericCompare<FileInfo>((fr1, fr2) => 
      { 
       return fr2.Length.CompareTo(fr1.Length); 
      }); 
     } 
     else 
     { 
      DefaultComparer = new GenericCompare<FileInfo>((fr1, fr2) => 
      { 
       return fr1.Name.ToLower().CompareTo(fr2.Name.ToLower()); 
      }); 
     } 

     var ordered_results = (new DirectoryInfo(@"C:\Temp")) 
       .GetFiles() 
       .OrderBy(fi => fi, DefaultComparer); 

बड़ा लाभ यह है कि आप तो मामले से प्रत्येक आदेश के लिए एक नया वर्ग बनाने की जरूरत नहीं है, आप बस एक नई लैम्ब्डा ऊपर तार कर सकते हैं। जाहिर है, इसे सभी प्रकार के तरीकों से बढ़ाया जा सकता है, इसलिए उम्मीद है कि यह कभी-कभी किसी, कहीं, किसी की मदद करेगा।

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