是否有一个简单的属性或数据合约可以分配给一个函数参数,以防止在C#/ .NET中传递null
?理想情况下,这也会在编译时进行检查,以确保文本null
没有在任何地方使用,并且在运行时抛出ArgumentNullException
。
目前我写的是......
if (null == arg)
throw new ArgumentNullException("arg");
...对于我期望不是null
的每一个论点。
同样,与Nullable<>
相反,以下内容会失败:
NonNullable<string> s = null; // throw some kind of exception
答案 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概述的决议是:
我们认为更多的是希望引用不为null。可空的引用类型 将是罕见的(虽然我们没有好的数据告诉我们 多少),所以它们应该需要一个新的注释。
该语言已经具有 - 和可为空的值类型的语法的概念。两者之间的类比将成为语言 在概念上更容易,语言更简单。
- 醇>
除非你主动决定你,否则你不应该为自己或你的消费者增加繁琐的空值 要他们。没有它们的空虚应该是那样的 你明确要选择加入。
所需功能的一个示例:
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 ..
}
不太理想我知道你必须记得在任何地方都默认,但这是一个解决方案。