Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/320.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 不可为空的类型_C# - Fatal编程技术网

C# 不可为空的类型

C# 不可为空的类型,c#,C#,有没有办法在C#中创建一个不可为空的类型(比如DateTime或TimeSpan) 还有一种方法(可能是属性)可以强制执行非空参数在不添加 if(arg1 == null) { throw new ArgumentNullException("this attribute is null") } 不可为Null的类型是ValueType,换句话说是结构。结构不能为null,因此示例如下: public struct MyStruct {} 没有内置的方法来确保null不会作为参数传递给

有没有办法在C#中创建一个不可为空的类型(比如DateTime或TimeSpan)

还有一种方法(可能是属性)可以强制执行非空参数在不添加

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在规范#中。