C# 用于检索';默认值';价值

C# 用于检索';默认值';价值,c#,generics,extension-methods,C#,Generics,Extension Methods,根据下面的示例,我正在讨论如何确定对象的默认值: 此特定扩展方法是为System.Type创建的。我试图做到的是让它更通用,我可以做这样的事情: int i = 3; bool amIaDefaultValue = i.IsDefaultValue(); 如果I==0(int的默认值),我希望返回true,对于所有其他实例,返回false 以下是我的初步尝试: public static bool IsDefaultValue<T>(this T value) { var

根据下面的示例,我正在讨论如何确定对象的默认值:

此特定扩展方法是为System.Type创建的。我试图做到的是让它更通用,我可以做这样的事情:

int i = 3;
bool amIaDefaultValue = i.IsDefaultValue();
如果I==0(int的默认值),我希望返回true,对于所有其他实例,返回false

以下是我的初步尝试:

public static bool IsDefaultValue<T>(this T value)
{
    var t = typeof(T); // always comes back as object..?

    if (t.IsValueType && Nullable.GetUnderlyingType(t) == null)
    {
        return value.Equals(Activator.CreateInstance<T>());
    }
    else
    {
        var defaultValue = default(T);

        if (value == null)
            return defaultValue == null;
        else
            return value.Equals(defaultValue);
    }
}
但是如果值恰好为null,我会立即得到一个错误。有没有一个很好的解决方案来实现这样的扩展方法?或者我应该坚持使用示例中经过尝试和测试的路线

编辑 正如评论中指出的那样,我似乎有点过于简单化了,没有找到问题的根源。下面是实际调用我的IsDefaultValue()的内容:

现在很明显,.GetValue总是作为System.Object返回。不明飞行物

在扩展方法中仍然可以将对象作为其基础类型吗?很抱歉给您带来混淆。

请看一下:

static class Program
{
    static void Main()
    {
        int a = 1;

        Console.WriteLine("a.IsDefaultValue() : " + a.IsDefaultValue());

        a = 0;

        Console.WriteLine("a.IsDefaultValue() : " + a.IsDefaultValue());

        object obj = new object();

        Console.WriteLine("obj.IsDefaultValue() : " + obj.IsDefaultValue());

        obj = null;

        Console.WriteLine("obj.IsDefaultValue() : " + obj.IsDefaultValue());

        int? b = 1;

        Console.WriteLine("b.IsDefaultValue() : " + b.IsDefaultValue());

        b = null;

        Console.WriteLine("b.IsDefaultValue() : " + b.IsDefaultValue());

        Console.ReadKey(true);
    }

    static bool IsDefaultValue<T>(this T value)
    {
        if (ReferenceEquals(value, null))
        {
            return true;
        }

        var t = value.GetType();

        if (t.IsValueType)
        {
            return value.Equals(Activator.CreateInstance(value.GetType()));
        }

        return false;
    }
}
静态类程序
{
静态void Main()
{
INTA=1;
Console.WriteLine(“a.IsDefaultValue():”+a.IsDefaultValue());
a=0;
Console.WriteLine(“a.IsDefaultValue():”+a.IsDefaultValue());
object obj=新对象();
Console.WriteLine(“obj.IsDefaultValue():”+obj.IsDefaultValue());
obj=null;
Console.WriteLine(“obj.IsDefaultValue():”+obj.IsDefaultValue());
int?b=1;
Console.WriteLine(“b.IsDefaultValue():”+b.IsDefaultValue());
b=零;
Console.WriteLine(“b.IsDefaultValue():”+b.IsDefaultValue());
Console.ReadKey(true);
}
静态布尔IsDefaultValue(此T值)
{
if(ReferenceEquals(value,null))
{
返回true;
}
var t=value.GetType();
if(t.IsValueType)
{
返回值.Equals(Activator.CreateInstance(value.GetType());
}
返回false;
}
}

显然有效(我必须说,我确信另一种方法应该有效,但不有效)

我看不到您正在描述的行为,使用
3.IsValueDefault()
调用您的方法,并在扩展方法中添加
控制台。WriteLine(t)
在控制台上生成预期的
System.Int32
<方法中的code>typeof(value)也可能是编译器错误。你没告诉我们什么?我也无法将“始终获取对象”复制为类型。当你调用该方法时,你确定
I
的设计时类型称为
int
?如中所示,您没有如下内容:
objecti=3;bool amIaDefaultValue=i.IsDefaultValue()?(另一方面,可以说您可能希望使用
value.GetType()
(检查null!)不管怎样,就像您传入一个值类型作为基本
对象
,或者传入一个它正在实现的接口,您将得到不正确的结果,因为
默认值(T)
将返回
null
)我不理解这个问题,但是要验证
某个东西有默认值并不简单,像
公共静态bool IsDefaultValue(这个T值){返回值==null | | value.Equals(default(T))}
?(cont),这可能不是一个可行的解决方案。除非您需要检查由值类型实现的接口,否则我认为您可以简单地检查
null
并始终返回
true
,否则请像现在这样执行值类型检查。如果它是引用类型且值非空,则返回
false
。如果它是值类型,请对照默认实例检查它。对于int?类型,IsDefaultValue()为0返回true,为null。对于null,它应该只返回true。我的印象是可空类型和泛型不能很好地结合在一起。
foreach (var imprintProperty in deltas.GetType().GetProperties())
{
    var value = imprintProperty.GetValue(deltas);
    if (!value.IsDefaultValue())
    {
        // get corresponding prop in programmable area
        var programmableProp = progarea.GetType().GetProperty(imprintProperty.Name);
        if (programmableProp != null)
            programmableProp.SetValue(progarea, value);
    }
}
static class Program
{
    static void Main()
    {
        int a = 1;

        Console.WriteLine("a.IsDefaultValue() : " + a.IsDefaultValue());

        a = 0;

        Console.WriteLine("a.IsDefaultValue() : " + a.IsDefaultValue());

        object obj = new object();

        Console.WriteLine("obj.IsDefaultValue() : " + obj.IsDefaultValue());

        obj = null;

        Console.WriteLine("obj.IsDefaultValue() : " + obj.IsDefaultValue());

        int? b = 1;

        Console.WriteLine("b.IsDefaultValue() : " + b.IsDefaultValue());

        b = null;

        Console.WriteLine("b.IsDefaultValue() : " + b.IsDefaultValue());

        Console.ReadKey(true);
    }

    static bool IsDefaultValue<T>(this T value)
    {
        if (ReferenceEquals(value, null))
        {
            return true;
        }

        var t = value.GetType();

        if (t.IsValueType)
        {
            return value.Equals(Activator.CreateInstance(value.GetType()));
        }

        return false;
    }
}