不可空的类型

有没有办法在C#中创建一个非可空类型(如DateTime或TimeSpan)。

还有一种方法(可能是一个属性)强制不会在没有添加的情况下将非null参数传递给方法和属性

if(arg1 == null) { throw new ArgumentNullException("this attribute is null") } 

DateTimeTimeSpan不可为空,因为它们是struct而不是class es。

至于你的第二个问题,在C#中没有标准的方法可以做到这一点。 你可以使用PostSharp(一个AOP框架)或者使用Spec#来实现这个目标,这是一种全新的语言(C#的扩展),它允许一些所需的行为。

您在.NET 4.0 / C#4.0中通过代码契约更容易引用的空检查,这几乎可以满足您的需求。

结构已经是非可空的,但不要像疯了一样创建自己的结构 – 你很少需要它们(类更常见)。 没有“非可空类”的真正概念; 人们提出了类似的语法更改:

 void Foo(string! arg1) {...} 

这将使编译器对arg1进行非空检查 – 但实际上,代码契约会做到这一点以及更多。 你可以在PostSharp中做一些事情,但它可能不值得这个hastle。

另一个关于非可空类的想法(以及未实现的原因之一); default(T)对于不可为空的类会是什么? ; -p规范要求 default(T)定义良好……

非可空类型是ValueType,换句话说是结构。 结构不能为null,因此示例如下:

 public struct MyStruct {} 

没有内置的方法可以确保null不作为参数传递给方法(除非参数的类型是ValueType)。 我已经看到人们创建扩展方法来做一个关于参数是否为null的更简单(即更少的代码)断言,这可能是你的选择。 另一方面,检查很短; 并且检查的意图非常清楚。 如果您使用自定义检查方法,则可能不是这种情况。

C#4.0将通过合同为这种编程添加更好的选项,但目前尚不可用。 正如另一个答案所指出的, PostSharp是一个做你想做的事情的选择。 PostSharp的工作原理是添加一个后编译步骤,其中添加了额外的代码。

但是,有一些选项可以静态检查是否可以传递null。 例如,ReSharper允许您使用[NotNull]属性装饰自己的方法参数,如果ReSharper可以确定参数可能为null,则它将在编译时发出警告。 当然,这只会警告您(可能)编码错误,它不是运行时检查,不应该这样使用。

你是对的:与C ++相比,这是C#的一个缺点。 这是一种耻辱,因为我传递给函数的所有参数中有95%是非空指针。 在C ++中,您可以添加编译器检查的文档,指出哪些指针可以指向某些内容。

除了提到的AOP解决方案之外,Enterprise Library还在其validation块中提供了此function。 http://msdn.microsoft.com/en-us/library/ff953182(v=pandp.50).aspx

结构(值类型)变量永远不会为空 – 这解释了您的DateTime案例。 因此,如果你的方法params是C#结构,你可以确定它们永远不会为null。
但是,如果您的方法参数是引用类型,则它们可以为null。 我不认为你可以取消上面在这种情况下显示的空检查。

当然,您可以编写自己的值类型( enumstruct ),它们不能为null(除非可以为空)。

至于第二部分,你可以有一个generics参数和一个只接受值类型的约束,这意味着参数不能为null – 考虑到我们使用class绝大多数情况,这不是很有用。

 public static void Do(T arg1) where T : struct { //both struct and enum goes here. } 

至于第二个问题,这是一个受Nullable启发的想法。

使用null检查参数的方法如下所示:

 void Foo(NotNull s) { var x = $"{s}"; var i = int.Parse(s); } 

NotNull用法不仅限于方法参数。 如果语言将来有一些语法糖,那将是非常好的,例如Foo(string! s)

 public struct NotNull 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) { return t.Value; } public static implicit operator NotNull(T t) { return new NotNull(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"); } } }