C# 不可为空的类型
有没有办法在C#中创建一个不可为空的类型(比如DateTime或TimeSpan) 还有一种方法(可能是属性)可以强制执行非空参数在不添加C# 不可为空的类型,c#,C#,有没有办法在C#中创建一个不可为空的类型(比如DateTime或TimeSpan) 还有一种方法(可能是属性)可以强制执行非空参数在不添加 if(arg1 == null) { throw new ArgumentNullException("this attribute is null") } 不可为Null的类型是ValueType,换句话说是结构。结构不能为null,因此示例如下: public struct MyStruct {} 没有内置的方法来确保null不会作为参数传递给
if(arg1 == null)
{
throw new ArgumentNullException("this attribute is null")
}
不可为Null的类型是ValueType,换句话说是结构。结构不能为null,因此示例如下:
public struct MyStruct {}
没有内置的方法来确保null不会作为参数传递给方法(除非参数的类型是ValueType)。我见过有人创建扩展方法来对参数是否为null进行更简单(即代码更少)的断言,这可能是您的一个选择。另一方面,支票一开始很短;检查的目的非常明确。如果使用自定义的检查方法,则情况可能并非如此
C#4.0将通过合同为此类编程增加更好的选项,但目前还不可用。正如在另一个答案中所指出的,这是一个做你想做的事情的选择。PostSharp的工作原理是在添加额外代码的地方添加编译后步骤
但是,有一些静态检查是否传递null的选项。例如,ReSharper允许您使用[NotNull]属性修饰自己的方法参数,如果ReSharper能够确定参数可能为null,它将在编译时发出警告。当然,这只是警告您(可能)错误的编码实践,它不是运行时检查,不应该这样使用 Structs(值类型)变量永远不会为空-这解释了DateTime的情况。因此,如果您的方法参数是C#结构,您可以确保它们永远不会为null。但是,如果方法参数是引用类型,则它们可以为null。我不认为您可以取消上面在这种情况下显示的空检查。
DateTime
和TimeSpan
不能为空,因为它们是struct
s而不是class
es
至于你的第二个问题,在C#中没有标准的方法可以做到这一点。您可以使用PostSharp(一种AOP框架)或with(一种全新的语言(C#的扩展)来实现这一点。在.NET 4.0/C#4.0中,通过代码契约,您所指的空值检查将更容易,这几乎是您想要的 结构已经是不可空的,但是不要疯狂地创建自己的结构——你很少需要它们(类更常见)。没有“不可为空类”的真正概念;人们提出了如下语法更改:
void Foo(string! arg1) {...}
这将使编译器在arg1
上执行非空检查-但实际上,代码契约会执行此操作以及更多操作。在PostSharp中,你可以做一些事情,但这可能不值得匆忙
关于不可空类的另一个想法(以及它们未实现的原因之一);对于不可为空的类,
default(T)
是什么-P规范要求<代码>默认(t)< /> >定义良好…你是对的:这是C++中与C++相比的缺点。这是一个遗憾,因为我传递给函数的所有参数中有95%是非空指针。在C++中,可以添加编译器检查文档,指示哪些指针被确保指向某个点。 < P>除了提到的AOP解决方案之外,企业库在其验证块中提供了这一点。
当然,您可以编写自己的值类型(
enum
和struct
),这些值类型不能为null(除非设置为null)
至于第二部分,您可以有一个泛型参数和一个仅接受值类型的约束,这意味着参数不能为null-考虑到我们使用的绝大多数情况下,class
,这不是很有用
public static void Do<T>(T arg1) where T : struct
{
//both struct and enum goes here.
}
public struct NotNull<T> where T : class
{
private T valueField;
public NotNull(T value)
{
this.valueField = value;
this.CheckNotNull(value);
}
public T Value => this.valueField;
public static implicit operator T(NotNull<T> t)
{
return t.Value;
}
public static implicit operator NotNull<T>(T t)
{
return new NotNull<T>(t);
}
public override bool Equals(object other)
{
return this.Value.Equals(other);
}
public override int GetHashCode()
{
return this.Value.GetHashCode();
}
public override string ToString()
{
return this.Value.ToString();
}
private void CheckNotNull(T value)
{
if (value == null)
{
throw new InvalidOperationException($"Value cannot be null");
}
}
}
publicstaticvoiddo(T arg1),其中T:struct
{
//结构和枚举都在这里。
}
至于第二个问题,这里有一个灵感来自Nullable
具有null检查参数的方法如下所示:
void Foo(NotNull<string> s)
{
var x = $"{s}";
var i = int.Parse(s);
}
根据Anders Hejlsberg在Microsoft Build 2019中的讲话,C#8.0将具有不可为空的类型。
如果您使用的是后期构建步骤,那么绝对有一种标准的方法可以做到这一点:代码契约是.NET 4的正式组成部分(并且在.NET 3.5中单独提供)。新语法方案和代码契约之间的区别在于可以静态地检查上述内容。对于现在阅读本文的人,代码契约现在实现静态检查。
string代码>在规范#中。