English 中文(简体)
我如何在 C# 中展示一个方法永远不会返回 null(契约式设计)?
原标题:
  • 时间:2009-01-27 18:18:29
  •  标签:

我有一种方法,从不返回空对象。我想让用户明白,这样他们就不必编写这样的代码:

if(Getxyz() != null)
{
  // do stuff
}

我该如何表达这个意图?

最佳回答

很遗憾,C#中没有内置的方法。

您可以记录此事实,但不会自动检查。

如果您正在使用Resharper,则可以在方法标记有[NotNull]属性时进行正确的检查设置。

否则,您可以使用[Microsoft Contracts][1]库,并向您的方法添加类似于以下内容的内容,但这对于如此简单的注释来说是相当多的废话。

Contract.Ensures(Contract.Result<string>() != null)

Spec#通过允许在类型后面加!来将其标记为非空类型,从而解决了这个问题,例如

string! foo

but Spec# can only be used to target .NET2, and has been usurped by the Code Contracts library. [1]: http://research.microsoft.com/en-us/projects/contracts/

问题回答

除非您使用的是基于System.ValueType的类型,否则我认为您没有太多的机会。最好在函数的XML/metadata注释中清楚地记录这一点。

我不知道使用API进行操作是否有最佳实践,因为我仍然会编写防御性程序并检查消费者是否为null。我认为在这种情况下,仍然这样做是最佳实践,因为我通常不想相信其他代码总是做正确的事情。

确保 C# 对象永远不会返回 null 的唯一类型检查的方法是使用结构体。结构体可以有包含空值的成员,但本身永远不会为 null。

所有其他C#对象都可以为空。

示例代码:

public struct StructExample
{
    public string Val;
}

public class MyClass
{
    private StructExamle example;

    public MyClass()
    {
        example = null; // will give you a  Cannot convert to null error
    }

    public StructExample GetXyz()
    {
        return null; // also gives the same error
    }
}

上面的例子无法编译。如果使用结构体是可接受的(它成为值类型,通过堆栈传递,无法被子类化),那么这个解决方案可能适合你。

我喜欢反过来考虑:如果我的函数可能返回空值,我最好确保函数的用户知道这一点。

如果您的用户使用像http://www.codeproject.com/KB/cs/designbycontract.aspx 这样的标准契约设计API来使用您的源代码,则可以使事情更加清楚。

否则你的最佳选择是通过文件。

你可以包括一个Debug.Assert()方法。虽然这肯定不会强制执行该条件,但它应该与文档一起清楚地表明,空值是不可接受的。

记录并提供源代码。(Jìlù bìng tígōng yuán dàimǎ.)

Either document it well (maybe with .NET standard documentation system) or you have to use some Contract API. Here are some: Link http://www.codeproject.com/KB/cs/designbycontract.aspx





相关问题
热门标签