简体   繁体   中英

LINQ FirstOrDefault test for null

Word1252_7bit is a struct
Key is Int32

How can I test for null if value is not found?

There is no w.Key == -1 but I don't know test for not value returned.

The last Debug line throws an exception.

List<Word1252_7bit> Words7bit = GetWord1252_7bit();

Word1252_7bit word1252_7bit ;

word1252_7bit = Words7bit.FirstOrDefault(w => w.Key == 1000);
Debug.WriteLine(word1252_7bit.Key.ToString() + " " + word1252_7bit.Value);

word1252_7bit = Words7bit.FirstOrDefault(w => w.Key == -1);
//if (word1252_7bit == null) Debug.WriteLine("word1252_7bit == null");
Debug.WriteLine( word1252_7bit.Key.ToString() + " " + word1252_7bit.Value ) ;

If I should use something other than FirstOrDefault let me know. Looking for speed searching on a unique Int32.

Not sure if it makes a difference but Key is unique and I use Key to override GetHashCode(), And to save space Key is really a piece of an UInt32

public Int32 Key
{
  get
  {
    return (Int32)( pack[0] & ( (1<<25) - 1 ) ) ;
  }
}

public struct Word1252_7bit : iWord
{
    // this maps 128 values to "Windows-1252" 
    // this is not ASCII 
    // this is SQL char 8bit normalized to FormD, remove control chars, remove redactions, and cast to lower - 129 - just have to cheat on 1
    private static byte[] Win1252_128to256 = new byte[] {  
             32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63
           , 64, 91, 92, 93, 94, 95, 96, 97, 98, 99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121
           ,122,123,124,125,126,128,130,131,132,133,134,135,137,139,145,146,147,148,149,150,151,152,153,155,156,160,161,162,163,164,165,166
           ,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,215,223,230,240,247,248,254 };
    private static Encoding win1252 = Encoding.GetEncoding("Windows-1252");
    private UInt32[] pack;
    public Int32 Key { get { return (Int32)(pack[0] & ((1 << 25) - 1)); } }
    public override bool Equals(Object obj)
    {
        // Check for null values and compare run-time types.
        if (obj == null) return false;
        if (!(obj is Word1252_7bit)) return false;
        Word1252_7bit comp = (Word1252_7bit)obj;
        if (comp.pack == null) return false;
        if (comp.pack.Count() == 0) return false;
        return (comp.Key == this.Key);
    }
    public override int GetHashCode()
    {
        return Key;
    }
    public byte[] Bytes
    {
        get
        {
            byte b;              
            List<byte> bytes = new List<byte>(((pack.Length - 1) * 4) + 1);

            b = (byte)((pack[0] >> 25) & ((1 << 7) - 1));
            bytes.Add(Win1252_128to256[b]);

            if (pack.Length > 1)
            {                       
                UInt32 cur32;
                byte bits4 = 0;
                byte bits3 = 0;
                for (int i = 1; i < pack.Length; i++)
                {
                    cur32 = pack[i];

                    if ((i-1) % 2 == 0)
                    {
                        bits4 = (byte)((cur32 >> 28) & ((1 << 4) - 1));
                    }
                    else
                    {   // pick up that odd i7
                        bits3 = (Byte)((cur32 >> 28) & ((1 << 3) - 1));
                        b = (byte)((UInt32)bits3 | ((UInt32)bits4 << 3));
                        if (b == 0) break;
                        bytes.Add(Win1252_128to256[b]);
                    }

                    b = (byte)(cur32         & ((1 << 7) - 1));
                    if (b == 0) break;
                    bytes.Add(Win1252_128to256[b]);

                    b = (byte)((cur32 >>  7) & ((1 << 7) - 1));
                    if (b == 0) break;
                    bytes.Add(Win1252_128to256[b]);

                    b = (byte)((cur32 >> 14) & ((1 << 7) - 1));
                    if (b == 0) break;
                    bytes.Add(Win1252_128to256[b]);

                    b = (byte)((cur32 >> 21) & ((1 << 7) - 1));
                    if (b == 0) break;
                    bytes.Add(Win1252_128to256[b]);

                    //Debug.WriteLine(win1252.GetString(bytes.ToArray()));   
                }
            }
            return bytes.ToArray();
        }
    }
    public String Value
    {
        get
        {
            return win1252.GetString(Bytes);
        }
    }
    public Int32 Lenght { get { return Bytes.Count(); } }
    public Word1252_7bit(UInt32[] Pack)
    {
        if(Pack == null) throw new IndexOutOfRangeException();
        if (Pack.Length == 0) throw new IndexOutOfRangeException();
        pack = Pack;
    }
}

FirstOrDefault<T> will return the first item found or the default value of T if none is found. For reference types this is null , but this is different for value types. For example, the default value of integers is 0 .

You can use the default keyword:

if (word1252_7bit.Equals(default(Word1252_7bit)))
    Debug.WriteLine("not found");

NOTE: You may have to write you're own override of Equals to get the result you expect.

In general, you won't be able to distinguish an item that was not found from an item that was found but which is equal to the default value. You can do this instead:

int foundAt = Words7bit.FindIndex(w => w.Key == -1);
if (foundAt == -1)
    Debug.WriteLine("not found");
else
    word1252_7bit = Words7bit[foundAt];

To have some more control you could define your own Default value, eg using something like:

public static T FirstOrDefault<T>(this IEnumerable<T> sequence, T defaultValue)
{
    foreach (var element in sequence)
        return element;
    return defaultValue; // default(T);
    // return sequence.Any() ? sequence.First() : defaultValue;
}

Then use it like

word1252_7bit = Words7bit.Where(w => w.Key == 1000)
    .FirstOrDefault(Word1252_7bit.Default);  

where 'Default' is a default instance defined for your struct. Something like...

public static readonly Word1252_7bit Default = new Word1252_7bit 
{ 
    Key = Int32.MinValue,
    Value = "default",
};

EDIT: Improved FirstOrDefault code (based on the original implementation)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM