RError.com

RError.com Logo RError.com Logo

RError.com Navigation

  • 主页

Mobile menu

Close
  • 主页
  • 系统&网络
    • 热门问题
    • 最新问题
    • 标签
  • Ubuntu
    • 热门问题
    • 最新问题
    • 标签
  • 帮助
主页 / 问题 / 713106
Accepted
Kunoichi
Kunoichi
Asked:2020-09-01 14:35:49 +0000 UTC2020-09-01 14:35:49 +0000 UTC 2020-09-01 14:35:49 +0000 UTC

检查对象的值是否为默认值。C#

  • 772

更新:此问题包含此问题下提供的功能的实现。最快的 V7 实施

您需要编写一个函数,该函数接受一个对象并返回该对象是否具有默认值。

public bool IsDefault(object o)
{
    return ...
}

现在我唯一想到的就是找出类型的名称,并通过switch检查对象是否具有该类型的默认值。它看起来像这样:

string typeName = o.GetType().Name;
switch (typeName)
{
    case "Int32":
        if(Convert.ToInt32(o) == 0)
        {
            return true;
        }
        return false;
    case "String":
        if (o == null || String.IsNullOrEmpty(Convert.ToString(o)))
        {
            return true;
        }
        return false;
        ...
        ...
        ...
}
c#
  • 5 5 个回答
  • 10 Views

5 个回答

  • Voted
  1. Best Answer
    nick_n_a
    2020-09-01T15:05:21Z2020-09-01T15:05:21Z

    我认为最好的选择是:

     bool isDefault<T>(T o) { return (o==null)?true: // считаем что null default
      o.GetType().IsValueType && !typeof(T).IsGenericType ? 
        o.Equals(Activator.CreateInstance(o.GetType())): // default типа который внутри nullable
        o.Equals(default(T)); // настоящий default
    }
    

    事实证明,如果对象中有演员表,则该对象有点“扭曲”。在这种情况下,有关模板的信息可能会丢失(Nullable 的一个有争议的问题)。对于“简单”类型,我在第二个条件中考虑了这一点。

    但最“正确”的是

        bool isDefault<T>(T o) { return (o==null)?(default(T)==null):o.Equals(default(T)); 
    

    同时,isDefault((object)0)此选项将给出false,因为 defalut(object) != 0开发人员可能不喜欢,这种情况只有在使用模板时才有用。根据您是使用模板类型还是将所有内容转换为对象,一种或另一种方式适合您。如果您希望 IsDefault((int?)0) 为真,则必须简化一点(删除 IsGenericType)。default(T)==null 的情况发生了,但是同时发生的可能性很小default(T)!=null,所以可以改写o == nulldefault(T)!=nulltrue

    剩下的留给历史吧……

    1. 通过反射(这里有一个 Cast in object 所以有些值会丢失,例如它IsDefault((int?)0)会给出 true

      class YourClass {
      
        public static T getDefault<T>() {
               return default(T);
             }
      
      public bool IsDefault(object o){
        if (o == null) return true; // условно
        object cmp = typeof(YourClass).GetMethod("getDefault")
        .MakeGenericMethod(new Type[]{   o.GetType() } ).Invoke(null,null);
        // теперь cmp содержит "дефолтное" значение
        bool equal = o.Equals(cmp); // дефолтное значение может быть null
       return equal;
       }
      

    为此,您需要连接两个像这样的问题 https://stackoverflow.com/questions/1895761/test-for-equality-to-the-default-value与这个https://stackoverflow.com/questions 连接 /6204326/调用-generic-method-using-reflection-in-net

    1. 如果您事先知道类型,那么您可以像这样简单地使用泛型而不使用反射

      bool isObjDefault<T>(object o) { return o.Equals(default(T)); }
      

      信息也在这里丢失 - 它IsDefault((int?)0)会给出真实的,

    所以,这样就更好了(原来你不需要指定类型,而且对象没有转换成对象,类型可能会因为转换而丢失)

        bool isDefault<T>(T o) { return (o==null)?true:o.Equals(default(T)); }
    
    1. 好吧,如果你有两种或三种类型,你可以这样做(没有泛型,只是类型比较):

      if (o is int) return o.Equals(default(int));
      if (o is string) return o.Equals(default(string));
      
    2. 另一个不寻常的“短”选项(它也适用于带有数字和字符串的类,虽然这个选项更耗费资源,但在一行中)

      public bool IsDefault(object o) {
        return (o==null)?true:o.GetType().Assembly.CreateInstance(o.GetType().FullName).Equals(o);
        }
      

      但是这种方法在没有默认值的情况下会创建一个空实例,所以在某些情况下是合适的。

    PS 1. 对于默认类,该值通常为 null(在工作室中它不为 null 的情况 - 我没有找到),包括泛型。对于 valuetype 和 struct 有默认值。

    1. 很多时候在程序中你可以看到所有类型的对象的使用。数据在对象的对流过程中可能会丢失,例如,Nullable<> 要么保留原始 null 没有类型,要么保留 int,而真正的类型会丢失。因此,您可以编写两个函数 f1(x) != f2(x),其中有一个转换就会有一个错误的值。
    • 10
  2. VladD
    2020-09-01T16:47:24Z2020-09-01T16:47:24Z

    我们无权“丢失”对象的真实类型,否则无法int?区分int。所以你必须做这样的事情:

    bool IsDefault<T>(T o)
    {
        if (o == null) // => ссылочный тип или nullable
            return true;
        if (Nullable.GetUnderlyingType(typeof(T)) != null) // nullable, не null
            return false;
        var type = o.GetType();
        if (type.IsClass)
            return false;
        else           // => тип-значение, есть конструктор по умолчанию
            return Activator.CreateInstance(type).Equals(o);
    }
    

    考试:

    Console.WriteLine(IsDefault(default(string))); // true
    Console.WriteLine(IsDefault(string.Empty));    // false
    Console.WriteLine(IsDefault(default(int)));    // true
    Console.WriteLine(IsDefault(1));               // false
    Console.WriteLine(IsDefault(default(int?)));   // true
    Console.WriteLine(IsDefault((int?)0));         // false
    Console.WriteLine(IsDefault((object)0));       // true
    Console.WriteLine(IsDefault((object)1));       // false
    

    在 object上,(object)(int?)0该方法将返回true,因为传递的对象是装箱的int,而不是装箱int?的(本质上不会发生)。

    • 10
  3. sp7
    2020-09-01T15:12:30Z2020-09-01T15:12:30Z

    可以像这样获得类型的默认值:

    public object GetDefaultValue(Type target)
    {
        Expression<Func<object>> e = Expression.Lambda<Func<object>>(
            Expression.Convert(
                Expression.Default(target), typeof(object)));
    
        return e.Compile()();
    }
    

    用法:

    public bool IsDefault(object o)
    {
        if(o == null)
            throw new ArgumentNullException(nameof(o));
    
        return o.Equals(GetDefaultValue(o.GetType()));
    }
    
    • 4
  4. RusArt
    2020-09-01T15:54:15Z2020-09-01T15:54:15Z

    最近c#语言更新到了7.1版本,现在可以这样写了:

    return (o is default);
    

    UPD 将不起作用,因为otype object,但是default(object) == null

    • 3
  5. VladD
    2020-09-02T00:56:34Z2020-09-02T00:56:34Z

    在我看来最快的另一种选择。让我们使用这里的技巧:

    class RequireStruct<T> where T : struct { }
    class RequireClass<T> where T : class { }
    
    static bool IsDefault<T>(T o, RequireClass<T> ignore = null) where T : class
    {
        if (o == null)
            return true;
        if (!(o is ValueType)) // не упакованная ли это структура?
            return false;      // нет - выходим
        return Activator.CreateInstance(o.GetType()).Equals(o); // медленный путь
    }
    static bool IsDefault<T>(T? o) where T : struct =>
        o == null;
    static bool IsDefault<T>(T o, RequireStruct<T> ignore = null) where T : struct =>
       default(T).Equals(o); // default(T) не требует рефлексии
    
    • 2

相关问题

Sidebar

Stats

  • 问题 10021
  • Answers 30001
  • 最佳答案 8000
  • 用户 6900
  • 常问
  • 回答
  • Marko Smith

    Python 3.6 - 安装 MySQL (Windows)

    • 1 个回答
  • Marko Smith

    C++ 编写程序“计算单个岛屿”。填充一个二维数组 12x12 0 和 1

    • 2 个回答
  • Marko Smith

    返回指针的函数

    • 1 个回答
  • Marko Smith

    我使用 django 管理面板添加图像,但它没有显示

    • 1 个回答
  • Marko Smith

    这些条目是什么意思,它们的完整等效项是什么样的

    • 2 个回答
  • Marko Smith

    浏览器仍然缓存文件数据

    • 1 个回答
  • Marko Smith

    在 Excel VBA 中激活工作表的问题

    • 3 个回答
  • Marko Smith

    为什么内置类型中包含复数而小数不包含?

    • 2 个回答
  • Marko Smith

    获得唯一途径

    • 3 个回答
  • Marko Smith

    告诉我一个像幻灯片一样创建滚动的库

    • 1 个回答
  • Martin Hope
    Air 究竟是什么标识了网站访问者? 2020-11-03 15:49:20 +0000 UTC
  • Martin Hope
    Алексей Шиманский 如何以及通过什么方式来查找 Javascript 代码中的错误? 2020-08-03 00:21:37 +0000 UTC
  • Martin Hope
    Qwertiy 号码显示 9223372036854775807 2020-07-11 18:16:49 +0000 UTC
  • Martin Hope
    user216109 如何为黑客设下陷阱,或充分击退攻击? 2020-05-10 02:22:52 +0000 UTC
  • Martin Hope
    Qwertiy 并变成3个无穷大 2020-11-06 07:15:57 +0000 UTC
  • Martin Hope
    koks_rs 什么是样板代码? 2020-10-27 15:43:19 +0000 UTC
  • Martin Hope
    user207618 Codegolf——组合选择算法的实现 2020-10-23 18:46:29 +0000 UTC
  • Martin Hope
    Sirop4ik 向 git 提交发布的正确方法是什么? 2020-10-05 00:02:00 +0000 UTC
  • Martin Hope
    faoxis 为什么在这么多示例中函数都称为 foo? 2020-08-15 04:42:49 +0000 UTC
  • Martin Hope
    Pavel Mayorov 如何从事件或回调函数中返回值?或者至少等他们完成。 2020-08-11 16:49:28 +0000 UTC

热门标签

javascript python java php c# c++ html android jquery mysql

Explore

  • 主页
  • 问题
    • 热门问题
    • 最新问题
  • 标签
  • 帮助

Footer

RError.com

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

帮助

© 2023 RError.com All Rights Reserve   沪ICP备12040472号-5