有没有办法在C#中创建非空类型(例如DateTime或TimeSpan)?
此外,是否有一种方法(可能是属性),可以强制执行不为空的参数不会传递给方法和属性,而无需添加 null
检查?
if(arg1 == null)
{
throw new ArgumentNullException("this attribute is null")
}
有没有办法在C#中创建非空类型(例如DateTime或TimeSpan)?
此外,是否有一种方法(可能是属性),可以强制执行不为空的参数不会传递给方法和属性,而无需添加 null
检查?
if(arg1 == null)
{
throw new ArgumentNullException("this attribute is null")
}
DateTime
和TimeSpan
是不可为空的,因为它们是struct
而不是class
。
至于您的第二个问题,在C#中没有标准方法可以实现此功能。您可以使用PostSharp这个AOP框架,或者使用Spec#,这是一种全新的语言(C#的扩展),允许实现一些所需的行为。
在.NET 4.0 / C# 4.0中,通过代码合同实现的空值检查将变得更加容易,这几乎可以满足您的需求。
结构体已经是非空的,但不要疯狂创建自己的结构体 - 您很少需要它们(类是更常见的)。没有真正的“非空类”概念; 人们已经提出了语法更改,例如:
void Foo(string! arg1) {...}
这将使编译器对arg1
进行非空检查-但实际上,代码合同会做更多的工作。在PostSharp中有一些你可以做的事情,但这可能不值得麻烦。
关于非空类的另一个想法(也是它们未被实现的原因之一); 对于非空类,default(T)
将是什么?;-p 规范要求default(T)
定义明确...
string!
在 Spec# 中。 - nawfalpublic struct MyStruct {}
是的!C# 8.0引入了非空引用类型: https://learn.microsoft.com/en-us/dotnet/csharp/nullable-references
string message = null;
// warning: dereference null.
Console.WriteLine($"The length of the message is {message.Length}");
var originalMessage = message;
message = "Hello, World!";
// No warning. Analysis determined "message" is not null.
Console.WriteLine($"The length of the message is {message.Length}");
// warning!
Console.WriteLine(originalMessage.Length);
这在新项目中默认启用。如果您更新现有项目的 .NET 版本,则不会自动启用,但您可以在 项目 -> 属性 -> 可空性
中启用它。
void Foo(NotNull<string> s)
{
var x = $"{s}";
var i = int.Parse(s);
}
NotNull<T>
的用法不仅限于方法参数。如果语言在未来有一些语法糖,例如 Foo(string! s)
,那肯定会很好。
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");
}
}
}
结构体(值类型)变量永远不会为null - 这就解释了你的DateTime案例。因此,如果你的方法参数是C#结构体,你可以确定它们永远不会为null。
然而,如果你的方法参数是引用类型,它们可能为null。在这种情况下,我认为你不能像上面展示的那样摆脱null检查。
当然,您可以编写自己的值类型(enum
和struct
),这些类型不能为null(除非可空)。
至于第二部分,您可以有一个泛型参数和一个只接受值类型的约束条件,这意味着参数不能为空 - 这在我们使用class
的绝大多数情况下并不是很有用。
public static void Do<T>(T arg1) where T : struct
{
//both struct and enum goes here.
}