在C#/ .NET中将参数标记为不可为空?

时间:2008-11-14 20:42:29

标签: c# .net parameters null

是否有一个简单的属性或数据合约可以分配给一个函数参数,以防止在C#/ .NET中传递null?理想情况下,这也会在编译时进行检查,以确保文本null没有在任何地方使用,并且在运行时抛出ArgumentNullException

目前我写的是......

if (null == arg)
  throw new ArgumentNullException("arg");

...对于我期望不是null的每一个论点。

同样,与Nullable<>相反,以下内容会失败:

NonNullable<string> s = null; // throw some kind of exception

6 个答案:

答案 0 :(得分:64)

不幸的是,在编译时没有任何可用的东西。

我最近在我的博客上发布了一些hacky solution,它使用了新的结构和转换。

在带有Code Contracts内容的.NET 4.0中,生活会更好。拥有实际的语言语法和支持非可空性仍然是非常好的,但代码契约将有很大的帮助。

我在MiscUtil中也有一个名为ThrowIfNull的扩展方法,这使得它更简单。

最后一点 - 使用“if (null == arg)”代替“if (arg == null)”的任何理由?我发现后者更容易阅读,前者在C中解决的问题不适用于C#。

答案 1 :(得分:15)

我知道这是一个非常古老的问题,但这里缺少这个问题:

如果您使用ReSharper,则可以使用Annotated Framework

答案 2 :(得分:12)

我知道我在这个问题上已经非常迟了,但我觉得答案会变得相关,因为C#的最新主要版本接近发布,然后发布。在C#8.0中将发生重大变化,C#将假定所有类型都被视为非空。

据Mads Torgersen说:

  

问题是空引用非常有用。在C#中,它们就是   每个引用类型的默认值。还有什么是默认的   价值是多少?变量有什么其他价值,直到你可以决定   还有什么可以分配给它?我们还有什么新的价值   已分配的引用数组,直到你到处   填写它?

     

此外,有时null本身就是一个明智的价值。有时   你想表示一个事实,比如说一个字段没有   值。可以为参数传递“无”。重点是   但有时候。这就是问题的另一部分:   像C#这样的语言不允许你表达这里的null是否为a   好主意与否。

所以Mads概述的决议是:

  
      
  1. 我们认为更多的是希望引用不为null。可空的引用类型   将是罕见的(虽然我们没有好的数据告诉我们   多少),所以它们应该需要一个新的注释。

  2.   
  3. 该语言已经具有 - 和可为空的值类型的语法的概念。两者之间的类比将成为语言   在概念上更容易,语言更简单。

  4.   
  5. 除非你主动决定你,否则你不应该为自己或你的消费者增加繁琐的空值   要他们。没有它们的空虚应该是那样的   你明确要选择加入。

  6.   

所需功能的一个示例:

public class Person
{
     public string Name { get; set; } // Not Null
     public string? Address { get; set; } // May be Null
}

预览适用于Visual Studio 2017,15.5.4+预览。

答案 3 :(得分:9)

查看企业库中的验证器。你可以这样做:

private MyType _someVariable = TenantType.None;
[NotNullValidator(MessageTemplate = "Some Variable can not be empty")]
public MyType SomeVariable {
    get {
        return _someVariable;
    }
    set {
        _someVariable = value;
    }
}

然后在您想要验证它的代码中:

Microsoft.Practices.EnterpriseLibrary.Validation.Validator myValidator = ValidationFactory.CreateValidator<MyClass>();

ValidationResults vrInfo = InternalValidator.Validate(myObject);

答案 4 :(得分:0)

不是最漂亮但是:

public static bool ContainsNullParameters(object[] methodParams)
{
     return (from o in methodParams where o == null).Count() > 0;
}

你也可以在ContainsNullParameters方法中获得更多创意:

public static bool ContainsNullParameters(Dictionary<string, object> methodParams, out ArgumentNullException containsNullParameters)
       {
            var nullParams = from o in methodParams
                             where o.Value == null
                             select o;

            bool paramsNull = nullParams.Count() > 0;


            if (paramsNull)
            {
                StringBuilder sb = new StringBuilder();
                foreach (var param in nullParams)
                    sb.Append(param.Key + " is null. ");

                containsNullParameters = new ArgumentNullException(sb.ToString());
            }
            else
                containsNullParameters = null;

            return paramsNull;
        }

当然你可以使用一个拦截器或反射,但这些很容易跟随/使用而且开销很小

答案 5 :(得分:-4)

好的,这个回复有点晚了,但这就是我解决问题的方法:

public static string Default(this string x)
{
    return x ?? "";
}

使用此exension方法,然后您可以将null和空字符串视为同一事物。

E.g。

if (model.Day.Default() == "")
{
    //.. Do something to handle no Day ..
}

不太理想我知道你必须记得在任何地方都默认,但这是一个解决方案。