Checking a structure's default value

2019-06-12 19:08发布

问题:

There is something wrong in my DefaultValue() function. It ALWAYS returns false, representing that the the structure is NOT the default value.

Why would this not work?

[StructLayout(LayoutKind.Sequential)]
private struct ArrayItem
{
    public long SrcSize;

    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 250)]
    public string SrcFile;

    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 250)]
    public string DestFile;
}

[StructLayout(LayoutKind.Sequential)]
private struct MyInfo
{
    public int Count;

    public int AppOne;

    public int AppTwo;

    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 100, ArraySubType = UnmanagedType.Struct)]
    public ArrayItem[] Files;
}


private bool DefaultValue<T>(T structure)
{
    if (EqualityComparer<T>.Default.Equals(structure, default(T)))
        return true;
    else
        return false;
}

//Success returns 'Value Changed' as expected
MyInfo fileInfoOne = new MyInfo();
fileInfoOne.Count = 3;
fileInfoOne.Files = new ArrayItem[100];
fileInfoOne.Files[0].SrcSize = 100;
Debug.Write("fileInfoOne: ");
if (DefaultValue(fileInfoOne.Files[0])) Debug.WriteLine("Default Value."); else Debug.WriteLine("Value Changed.");


//Fails but has all the default settings, should return 'Default Value'
MyInfo fileInfoTwo = new MyInfo();
fileInfoTwo.Files = new ArrayItem[100];
fileInfoTwo.Files[0].SrcSize = 0;
fileInfoTwo.Files[0].SrcFile = "";
fileInfoTwo.Files[0].DestFile = "";
Debug.Write("fileInfoTwo: ");
if (DefaultValue(fileInfoTwo.Files[0])) Debug.WriteLine("Default Value."); else Debug.WriteLine("Value Changed.");

回答1:

No worry, your DefaultValue() function is just fine :)

But when you calling it, make sure you don't initialize the test struct members with empty array/string objects. default means 0(zero) for value types and null for reference types. NET Framework Arrays and Strings are reference types, so if they are not null, the function will report them as non default.



回答2:

In the hopes this might help someone else out too... I have come up with a work around for my situation. In my case (dealing with memory mapping) I pass a null value into a memory map and that null value eventually gets read as a blank string (""). Because of this I ended up coming up with this function to check (account) for blank strings. This only works for me because I know that if my string are blank they are invalid anyway so they might as well be null).

private bool NoFile<T>(T structure)
{
    bool valueIsDefault = true;

    foreach (FieldInfo f in typeof(T).GetFields())
    {
        object defaultVal = f.GetValue(default(T));
        object structVal = f.GetValue(structure);
        if (structVal.GetType() == typeof(string) && (string)structVal == "") structVal = null;

        if (!object.Equals(structVal, defaultVal))
        {
            valueIsDefault = false;
            break;
        }
    }

    return valueIsDefault;
}