कैसे जांचें कि यदि IEnumerable शून्य या खाली है?


155

मुझे string.IsNullOrEmptyविधि पसंद है। मुझे कुछ ऐसा करना पसंद होगा जो IEnumerable के लिए समान कार्यक्षमता की अनुमति देगा। क्या ऐसा है? शायद कुछ संग्रह सहायक वर्ग? कारण मैं पूछ रहा हूं कि ifयदि संरक्षक है तो बयानों में कोड अव्यवस्थित दिखता है (mylist != null && mylist.Any())। यह बहुत क्लीनर होगा Foo.IsAny(myList)

यह पोस्ट उस उत्तर को नहीं देती: IEnumerable खाली है?


1
@msarchet: मैं शायद आपको इसका जवाब दूंगा अगर यह टिप्पणी नहीं थी :)
Schultz9999

मुझे यह एक XY समस्या की तरह लगता है। यह पूछने के बजाय कि "मैं इसे कैसे परेशान कर सकता हूं, क्योंकि यह बिल्कुल परेशान हो सकता है"
सारा

@nawfal, आपके द्वारा जुड़े प्रश्न में विशेष रूप से अशक्त चेक शामिल नहीं हैं, इसलिए मैं इसे डुप्लिकेट नहीं
मानूंगा

जवाबों:


188

यकीन है कि आप लिख सकते हैं :

public static class Utils {
    public static bool IsAny<T>(this IEnumerable<T> data) {
        return data != null && data.Any();
    }
}

हालांकि, सतर्क रहें कि सभी अनुक्रम दोहराए जाने योग्य नहीं हैं; आम तौर पर मैं केवल एक बार उन्हें चलना पसंद करता हूं, बस मामले में।


12
क्या यह एक अच्छा पैटर्न है? मैं thisवहां छोड़ दूंगा - मैं विस्तार के तरीकों पर विचार करता हूं, जिन्हें nullबदसूरत डिजाइन का संकेत माना जाता है ।
मोर्मगिल

28
@Mormegil क्यों? विस्तार विधियां अंत में नलियों के साथ काम करने की सी # कुछ क्षमता देती हैं, जो अन्य भाषाओं (जैसे रूबी) पूरी तरह से दी जाती हैं।
मैट ग्रीर

5
यह जरूरी क्यों बुरा है? जैसा कि इस मामले में, यह कभी-कभी बहुत आसान होता है क्योंकि यह आपको चीजों को अधिक सजातीय और कम विशेष मामलों के साथ व्यवहार करने देता है।
मिस्टर पुट्टी

5
@Mormegil meh - मैं इसके बारे में उत्साहित नहीं हो सकता। जब तक इरादे स्पष्ट, आदि है
मार्क Gravell

6
@ मिरिफा .Any()एक विस्तार विधि है जो IEnumerable<T>(या IQueryable<T>, हालांकि यह एक अलग परिदृश्य है) संचालित होती है । ऐसा करने से अनुक्रम कम हो जाता है, कम से कम आंशिक रूप से (हालांकि इसका मतलब है कि यह अभी भी खपत है) - यह केवल एक तत्व को पढ़ने की आवश्यकता हो सकती है (विशेषकर यदि कोई विधेय नहीं है)। जैसे, चूंकि अनुक्रम ( IEnumerable<T>) को दोहराने योग्य होने की आवश्यकता नहीं है, इसलिए यह हो सकता हैAny()एक विधेय के बिना है अनिवार्य रूप से करने के लिए बराबर foreach(var x in sequence) { return true; } return false;है - हालांकि इसे इस्तेमाल करता है GetEnumerator()आदि संकलक वाक्य रचना के बजाय
मार्क Gravell

120
public static bool IsNullOrEmpty<T>(this IEnumerable<T> enumerable) {
    return enumerable == null || !enumerable.Any();
}

8
ठीक है, काफी नहीं, ओपी ने IEnumerable के लिए पूछा, न कि IEnumerable <T> ;-)
yoyo

8
हाँ, IEnumerableकोई Any()विस्तार नहीं है।
Blaise

23

यहां @Matt Greer के उपयोगी उत्तर का एक संशोधित संस्करण है जिसमें एक स्थिर आवरण वर्ग शामिल है, ताकि आप इसे एक नई स्रोत फ़ाइल में कॉपी-पेस्ट कर सकें, Linq पर निर्भर न हों, और IEnumerable<T>मूल्य प्रकारों की बॉक्सिंग से बचने के लिए एक सामान्य अधिभार जोड़ता है। यह गैर-सामान्य संस्करण के साथ होगा। [संपादित करें: ध्यान दें कि IEnumerable<T>एन्यूमरेटर के बॉक्सिंग को रोकना नहीं है, बतख-टाइपिंग को रोका नहीं जा सकता है, लेकिन कम से कम मूल्य-टाइप किए गए संग्रह के तत्व प्रत्येक बॉक्सिंग नहीं होंगे।]

using System.Collections;
using System.Collections.Generic;

public static class IsNullOrEmptyExtension
{
    public static bool IsNullOrEmpty(this IEnumerable source)
    {
        if (source != null)
        {
            foreach (object obj in source)
            {
                return false;
            }
        }
        return true;
    }

    public static bool IsNullOrEmpty<T>(this IEnumerable<T> source)
    {
        if (source != null)
        {
            foreach (T obj in source)
            {
                return false;
            }
        }
        return true;
    }
}

15

एक और तरीका होगा एन्यूमरेटर और मूवनेक्स्ट () विधि को कॉल करने के लिए यह देखने के लिए कि क्या कोई आइटम हैं:

if (mylist != null && mylist.GetEnumerator().MoveNext())
{
    // The list is not null or empty
}

यह IEnumerable के साथ-साथ IEnumerable <T> के लिए काम करता है।


4
क्या आपको इस एन्यूमरेटर पर डिस्पोजल देना चाहिए? यदि संग्रह बहु-जागरूक है? हाँ। stackoverflow.com/questions/13459447/…
TamusJRoyce

2
@TamusJRoyce ध्यान दें कि आपका कथन केवल सत्य है IEnumerable<T>, क्योंकि गैर-जेनेरिक IEnumerableलागू नहीं होता है IDisposable
इयान केम्प

9

जिस तरह से मैं इसे करता हूं, कुछ आधुनिक सी # सुविधाओं का लाभ उठा रहा हूं:

विकल्प 1)

public static class Utils {
    public static bool IsNullOrEmpty<T>(this IEnumerable<T> list) {
        return !(list?.Any() ?? false);
    }
}

विकल्प 2)

public static class Utils {
    public static bool IsNullOrEmpty<T>(this IEnumerable<T> list) {
        return !(list?.Any()).GetValueOrDefault();
    }
}

और वैसे, कभी भी उपयोग न करें Count == 0या Count() == 0सिर्फ यह जांचने के लिए कि क्या संग्रह खाली है। हमेशा Linq का उपयोग करें.Any()


2
गिनती == 0 बस ठीक है .... हो सकता है किसी से भी तेज ()? हालाँकि आप काउंट पर सही हैं () == 0 खराब है। उन लोगों के लिए जो सोच रहे हैं कि गणना () आपके पूरे संग्रह के माध्यम से पुनरावृत्त करता है, इसलिए यदि यह बहुत बड़ा है तो एक टन ओवरहेड जोड़ सकता है!
एंथनी निकोल्स

गणना () केवल गणना को पुनरावृत्त करता है यदि इसे एक ICollection में नहीं डाला जा सकता है। दूसरे शब्दों में, जब आप इस विधि को कहते हैं, यदि पहले से ही ऑब्जेक्ट पर एक गणना गुण है, तो यह बस वापस आ जाएगा और प्रदर्शन समान होना चाहिए। कार्यान्वयन यहाँ देखें: referenceource.microsoft.com/#System.Core/System/Linq/…
Ronald Rey

यदि आप एक IEnumerable के साथ काम कर रहे हैं, तो रिक्तता के लिए परीक्षण करने के लिए गणना () का उपयोग करना निश्चित रूप से एक बुरा विचार है क्योंकि Linq कार्यान्वयन पूरे संग्रह पर पुनरावृति करेगा, जबकि कोई भी केवल एक बार पुनरावृत्त को स्थानांतरित करेगा। ध्यान रखें कि आप इस मामले में गिनती संपत्ति का उपयोग नहीं कर सकते क्योंकि यह IEnumerable इंटरफ़ेस का हिस्सा नहीं है। इसीलिए मेरी राय में सभी परिदृश्यों में रिक्तता के परीक्षण के लिए किसी भी () का उपयोग करने के लिए हमेशा एक बेहतर विचार है।
रोनाल्ड री

पठनीय नकारात्‍मक संचालक !विशेष रूप से दूसरे विकल्‍प में कैसे हो सकता है, इसका अच्‍छा उदाहरण ;
फैबियो


5

C # 6 से शुरू करके आप अशक्त प्रचार का उपयोग कर सकते हैं :myList?.Any() == true

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

उनके जवाब एक ही बुनियादी कार्यक्षमता प्रदान करते हैं, लेकिन प्रत्येक दूसरे दृष्टिकोण से। मैट के जवाब में string.IsNullOrEmpty-मेंटिटी का इस्तेमाल किया गया है, जबकि मार्क का जवाब लिनक का है.Any() काम पाने के राह है।

मैं व्यक्तिगत रूप से .Any()सड़क का उपयोग करने के लिए इच्छुक हूं , लेकिन विधि के अन्य अधिभार से स्थिति की जांच की कार्यक्षमता जोड़ना चाहता हूं :

    public static bool AnyNotNull<T>(this IEnumerable<T> source, Func<T, bool> predicate = null)
    {
        if (source == null) return false;
        return predicate == null
            ? source.Any()
            : source.Any(predicate);
    }

तो आप अभी भी ऐसी चीजें कर सकते हैं: myList.AnyNotNull(item=>item.AnswerToLife == 42);जैसा कि आप नियमित रूप से कर सकते हैं.Any() लेकिन अतिरिक्त नल की जांच के साथ

ध्यान दें कि C # 6 तरीके से: के बजाय myList?.Any()एक रिटर्न देता bool?है bool, जो अशक्त प्रचार का वास्तविक प्रभाव है


1
संग्रह के साथ समस्या? कोई भी () यह सकर्मक नहीं है। जब null, collection। संग्रह .Any () == true असत्य है, लेकिन कलेक्शन? .Any () == असत्य भी असत्य है। इसके अलावा; संग्रह? .Any () == झूठा भी गलत है ...
जैकब सजुक्विविक्ज़

4
if (collection?.Any() == true){
    // if collection contains more than one item
}
if (collection?.Any() != true){
    // if collection is null
    // if collection does not contain any item
}

2

यहां मार्क ग्रेवेल के उत्तर का कोड है , साथ ही इसका उपयोग करने का एक उदाहरण है।

using System;
using System.Collections.Generic;
using System.Linq;

public static class Utils
{
    public static bool IsAny<T>(this IEnumerable<T> data)
    {
        return data != null && data.Any();
    }
}

class Program
{
    static void Main(string[] args)
    {
        IEnumerable<string> items;
        //items = null;
        //items = new String[0];
        items = new String[] { "foo", "bar", "baz" };

        /*** Example Starts Here ***/
        if (items.IsAny())
        {
            foreach (var item in items)
            {
                Console.WriteLine(item);
            }
        }
        else
        {
            Console.WriteLine("No items.");
        }
    }
}

जैसा कि वे कहते हैं, सभी अनुक्रम दोहराए जाने योग्य नहीं हैं, इसलिए यह कोड कभी-कभी समस्या पैदा कर सकता है, क्योंकि IsAny()अनुक्रम के माध्यम से आगे बढ़ना शुरू होता है। मुझे संदेह है कि रॉबर्ट हार्वे के जवाब का मतलब यह था कि आपको अक्सर जांच करने null और खाली करने की आवश्यकता नहीं है । अक्सर, आप बस नल की जांच कर सकते हैं और फिर उपयोग कर सकते हैं foreach

अनुक्रम को दो बार शुरू करने और इसका लाभ उठाने से बचने के लिए foreach, मैंने कुछ कोड इस तरह लिखे:

using System;
using System.Collections.Generic;
using System.Linq;

class Program
{
    static void Main(string[] args)
    {
        IEnumerable<string> items;
        //items = null;
        //items = new String[0];
        items = new String[] { "foo", "bar", "baz" };

        /*** Example Starts Here ***/
        bool isEmpty = true;
        if (items != null)
        {
            foreach (var item in items)
            {
                isEmpty = false;
                Console.WriteLine(item);
            }
        }
        if (isEmpty)
        {
            Console.WriteLine("No items.");
        }
    }
}

मुझे लगता है कि एक्सटेंशन विधि आपको टाइपिंग की कुछ पंक्तियाँ सहेजती है, लेकिन यह कोड मुझे स्पष्ट लगता है। मुझे संदेह है कि कुछ डेवलपर्स तुरंत महसूस नहीं IsAny(items)करेंगे कि वास्तव में अनुक्रम के माध्यम से आगे बढ़ना शुरू हो जाएगा। (बेशक यदि आप बहुत सारे दृश्यों का उपयोग कर रहे हैं, तो आप जल्दी से उनके बारे में क्या कदम उठाते हैं, इस बारे में सोचना सीखें।)


यदि आप IsAny को एक अशक्त कहते हैं, तो यह अपवाद छोड़ देगा
Ace Trajkov

3
क्या आपने इसे आज़माया, @Ace? ऐसा लगता है कि यह एक अपवाद को फेंक देगा, लेकिन विस्तार के तरीकों को शून्य उदाहरणों पर बुलाया जा सकता है
डॉन किर्कबी

2

मैं उपयोग करता हूं Bool IsCollectionNullOrEmpty = !(Collection?.Any()??false); । उम्मीद है की यह मदद करेगा।

टूट - फूट:

Collection?.Any()nullयदि संग्रह शून्य है, और falseयदि संग्रह खाली है तो वापस आ जाएगा ।

Collection?.Any()??falsefalseअगर संग्रह खाली है, और falseसंग्रह है , तो हमें दे देंगेnull

उस का पूरक हमें दे देंगे IsEmptyOrNull


2

जॉन स्कीट का anwser ( https://stackoverflow.com/a/28904021/8207463 ) NULL और EMPTY के लिए Extension Method - Any () का उपयोग करके एक अच्छा तरीका है। लेकिन वह सवाल के मामले में मान्य नहीं है, जिसके लिए वह पूरा नहीं है। तो ध्यान से बदलने के लिए जॉन के दृष्टिकोण को निम्नलिखित के रूप में मान्य करें:

If (yourList?.Any() != true) 
{
     ..your code...
}

उपयोग न करें (NULL को मान्य नहीं करेगा):

If (yourList?.Any() == false) 
{
     ..your code...
}

आप नॉट नॉट के रूप में मान्य होने की स्थिति में भी हो सकते हैं (उदाहरण के तौर पर बिना कंपाइलर त्रुटि के परीक्षण किए गए) विधेय का उपयोग करने जैसा कुछ करें:

If (yourList?.Any(p => p.anyItem == null) == true) 
{
     ..your code...
}

https://referencesource.microsoft.com/#System.Core/System/Linq/Enumerable.cs,8788153112b7ffd0

किस .NET संस्करण के लिए आप इसका उपयोग कर सकते हैं कृपया जाँच करें:

https://docs.microsoft.com/en-us/dotnet/api/system.linq.enumerable.any?view=netframework-4.8#moniker-applies-to


1

मुझे भी यही समस्या थी और मैं इसे हल करता हूं:

    public bool HasMember(IEnumerable<TEntity> Dataset)
    {
        return Dataset != null && Dataset.Any(c=>c!=null);
    }

"c => c! = null" सभी अशक्त संस्थाओं की उपेक्षा करेगा।


1

मैंने @Matt Greer द्वारा उत्तर के इस बंद का निर्माण किया

उन्होंने ओपी के सवाल का पूरी तरह से जवाब दिया।

मैं किसी भी तरह की मूल क्षमताओं को बनाए रखते हुए कुछ इस तरह से चाहता था, जबकि शून्य के लिए भी जाँच कर रहा था। मैं इस मामले में किसी और की जरूरत है कुछ इसी तरह पोस्ट कर रहा हूँ।

विशेष रूप से मैं अभी भी एक विधेय में पारित करने में सक्षम होना चाहता था।

public static class Utilities
{
    /// <summary>
    /// Determines whether a sequence has a value and contains any elements.
    /// </summary>
    /// <typeparam name="TSource">The type of the elements of source.</typeparam>
    /// <param name="source">The <see cref="System.Collections.Generic.IEnumerable"/> to check for emptiness.</param>
    /// <returns>true if the source sequence is not null and contains any elements; otherwise, false.</returns>
    public static bool AnyNotNull<TSource>(this IEnumerable<TSource> source)
    {
        return source?.Any() == true;
    }

    /// <summary>
    /// Determines whether a sequence has a value and any element of a sequence satisfies a condition.
    /// </summary>
    /// <typeparam name="TSource">The type of the elements of source.</typeparam>
    /// <param name="source">An <see cref="System.Collections.Generic.IEnumerable"/> whose elements to apply the predicate to.</param>
    /// <param name="predicate">A function to test each element for a condition.</param>
    /// <returns>true if the source sequence is not null and any elements in the source sequence pass the test in the specified predicate; otherwise, false.</returns>
    public static bool AnyNotNull<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate)
    {
        return source?.Any(predicate) == true;
    }
}

विस्तार विधि का नामकरण बेहतर हो सकता है।


0

खाली की जाँच करने के लिए नीचे या अन्य सबसे अच्छा समाधान है या नहीं?

for(var item in listEnumerable)
{
 var count=item.Length;
  if(count>0)
  {
         // not empty or null
   }
  else
  {
       // empty
  }
}

1
अगर listEnumerableअशक्त है, जो काम नहीं करेगा , जो सवाल है
तिमोटी

0

मैं इस एक का उपयोग करें:

    public static bool IsNotEmpty(this ICollection elements)
    {
        return elements != null && elements.Count > 0;
    }

Ejem:

List<string> Things = null;
if (Things.IsNotEmpty())
{
    //replaces ->  if (Things != null && Things.Count > 0) 
}

0

चूँकि एक पढ़ने के बाद कुछ संसाधन समाप्त हो जाते हैं, मैंने सोचा कि पारंपरिक अलग चेक के बजाय चेक और रीड को संयोजित क्यों नहीं किया जाए, फिर पढ़ें।

पहले हमारे पास सरल चेक-इन-नल इनलाइन एक्सटेंशन के लिए एक है:

public static System.Collections.Generic.IEnumerable<T> ThrowOnNull<T>(this System.Collections.Generic.IEnumerable<T> source, string paramName = null) => source ?? throw new System.ArgumentNullException(paramName ?? nameof(source));

var first = source.ThrowOnNull().First();

फिर हमारे पास थोड़ा और शामिल है (ठीक है, कम से कम जिस तरह से मैंने इसे लिखा था) चेक-इन-नल-एंड-इनलाइन एक्सटेंशन के लिए:

public static System.Collections.Generic.IEnumerable<T> ThrowOnNullOrEmpty<T>(this System.Collections.Generic.IEnumerable<T> source, string paramName = null)
{
  using (var e = source.ThrowOnNull(paramName).GetEnumerator())
  {
    if (!e.MoveNext())
    {
      throw new System.ArgumentException(@"The sequence is empty.", paramName ?? nameof(source));
    }

    do
    {
      yield return e.Current;
    }
    while (e.MoveNext());
  }
}

var first = source.ThrowOnNullOrEmpty().First();

आप निश्चित रूप से कॉल श्रृंखला को जारी रखे बिना दोनों को कॉल कर सकते हैं। इसके अलावा, मैंने परमनाम को शामिल किया, ताकि कॉल करने वाले को त्रुटि के लिए एक वैकल्पिक नाम शामिल हो सके अगर यह "स्रोत" की जाँच नहीं की जा रही है, जैसे "नेमॉफ़ (लक्ष्य)"।


0
 public static bool AnyNotNull<TSource>(this IEnumerable<TSource> source)
    {
        return source != null && source.Any();
    }

शून्य और किसी भी जाँच करने के लिए अपने स्वयं के विस्तार विधि


0

कस्टम सहायकों के बिना मैं ?.Any() ?? falseया तो सलाह देता हूं या ?.Any() == trueजो अपेक्षाकृत संक्षिप्त हैं और केवल एक बार अनुक्रम निर्दिष्ट करने की आवश्यकता है।


जब मैं एक खाली संग्रह की तरह एक लापता संग्रह का इलाज करना चाहता हूं, तो मैं निम्नलिखित एक्सटेंशन विधि का उपयोग करता हूं:

public static IEnumerable<T> OrEmpty<T>(this IEnumerable<T> sequence)
{
    return sequence ?? Enumerable.Empty<T>();
}

इस फ़ंक्शन को सभी LINQ विधियों के साथ जोड़ा जा सकता है और foreach, बस नहीं .Any(), यही वजह है कि मैं इसे अधिक विशिष्ट सहायक कार्यों से अधिक पसंद करता हूं जो लोग यहां प्रस्तावित कर रहे हैं।


0

मैं उपयोग करता हूं

    list.Where (r=>r.value == value).DefaultIfEmpty().First()

यदि कोई मिलान नहीं है, तो परिणाम शून्य होगा, अन्यथा वस्तुओं में से एक को वापस कर दिया जाएगा

यदि आप सूची चाहते थे, तो मेरा मानना ​​है कि फर्स्ट () को छोड़ना या ToList () को कॉल करना सूची या अशक्तता प्रदान करेगा।



-1

using System.Linqजब आप उपलब्ध विधियों को एक्सेस करने का प्रयास करते हैं तो बस जादू जोड़ें और देखें IEnumerable। इसे जोड़ने से आपको Count()सरल नाम की विधि तक पहुंच प्राप्त होगी । बस null valueकॉल करने से पहले जांच करना याद रखें count():)


-1

अगर इसके लिए जाँच की जाए तो मैंने सरल का उपयोग किया है

मेरे समाधान की जाँच करें

foreach (Pet pet in v.Pets)
{
    if (pet == null)
    {
        Console.WriteLine(" No pet");// enumerator is empty
        break;
    }
    Console.WriteLine("  {0}", pet.Name);
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.