Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/295.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# 实施方法don';t返回空值_C#_Oop_Null_Nullreferenceexception - Fatal编程技术网

C# 实施方法don';t返回空值

C# 实施方法don';t返回空值,c#,oop,null,nullreferenceexception,C#,Oop,Null,Nullreferenceexception,正如8年前提出的问题,但我认为应该有一种方法(新模式、新设计、新架构或其他任何东西)来强制方法不要返回null 正如您所知,在方法中返回null有一些含义,对我来说重要的一点是: 在消费端处理null和可理解的语义,如: 方法: public ClassName Do() { ... return null; } 并调用Do()类似(注意注释): 在通过上述方式对产品提出了许多问题之后,我得出了这个结论,概括了所有方法,以遵循一种模式,使其可读、清晰,并防止语义歧义 所以一个非

正如8年前提出的问题,但我认为应该有一种方法(新模式、新设计、新架构或其他任何东西)来强制方法不要返回null

正如您所知,在方法中返回null有一些含义,对我来说重要的一点是:

在消费端处理null和可理解的语义,如:

方法:

public ClassName Do()
{
    ...
    return null;
}
并调用
Do()
类似(注意注释):

在通过上述方式对产品提出了许多问题之后,我得出了这个结论,概括了所有方法,以遵循一种模式,使其可读、清晰,并防止语义歧义

所以一个非常基本的方法是使用
Struct
type,因为structure不能为null,如果方法的返回类型是structure,那么它们就不能返回null,我们在编译时知道这一点,而不是在运行时

因此,我实现了上述方法,如:

1-将方法的DTO
out
in
,在这种情况下,只需
out

public struct Do_DTO_Out
{
    public ClassName Prop1 { get; set; }
    public bool IsEmpty
    {
        get
        {
            return Prop1 == null;
        }
    }

    public static Do_DTO_Out Empty
    {
        get
        {
            return new Do_DTO_Out() { Prop1 = null };
        }
    }
}
2-和
Do
方法应为:

public Do_DTO_Out Do()
{
    try
    {
        return manipulatedObj;
    }
    catch (Exception exp)
    {

    }
    return Do_DTO_Out.Empty;
}
3-在消费方面:

var objVal = Do();
if (!objVal.IsEmpty)
    //Do something
结构是不是最好的方法?是否值得更改所有方法并为每个方法创建DTO
in
out
(我认为是这样)


如果有更好的方法,任何想法、帮助和答案都将不胜感激。

您的“引用类型”到“带属性检查的结构”转换对我来说似乎毫无用处。它还需要对您的意图有深入的了解,而引用类型null检查对于以后阅读它的任何人来说都是非常明显的

我想这对你有用。它为您提供编译时静态分析和运行时检查。只要确保你有合适的合同作为岗位条件:

public ClassName Do()
{
    ...

    object returnValue = null;

    Contract.Ensures(returnValue != null);

    return returnValue;
}

假设该值永远不能为
null
,否则
if
是不可避免的(但对于单个方法调用,您现在可以编写
Do()?.DoSomething()

如果您可以引入代码契约(请参阅),那么我完全同意Patrick的观点,您应该遵循它们。如果它不可行(因为您的代码库已经太大,或者您的目标环境不支持它们),那么我首先使用断言:

var obj = Do();
Debug.Assert(obj != null);

// Use obj...
然而,我们正在将这一责任转移到呼叫点,这可能是乏味的。如果您想使这个接口显式化,那么您可以像您所想的那样使用struct,但在调用点抛出异常(错误是):

现在,来电者可以是:

MyClass obj = Do();
obj.DoSomthing();
当创建对象时,会抛出适当的异常(不幸的是在运行时)。使用
[Conditional(“DEBUG”)]
时,您可以排除对具有类似于
DEBUG.Assert()
的行为且开销最小(但仍然存在)的发布版本的检查

请注意,只有当您希望在其签名中直接记录有关此约束的接口方法时,这才有意义。如果您对此不感兴趣,请尽量简单:

public SomeClass Do()
{
    MyClass somevalue = ...

    // ...

    return NotNull(somevalue);
}
其中,
NotNull()
是一个在某处定义的静态方法,它与使用static的
一起导入,甚至是一个名为
return somevalue.NotNull()的
对象的扩展方法


我并不特别喜欢这种方法,因为我认为在这种情况下,
Debug.Assert()
就足够了,但这只是我的观点。当然,也许有一天我们会使用C语言,然后我们会得到编译时强制(作为
对象?
,或者反过来作为
对象!
)。

返回null是一种不好的做法-最好实现

@Aria方法不会返回
null
,因为它返回的是一个结构,但它仍然返回一个带有空引用的结构,如果您检查
IsEmpty
,那么您拥有相同的代码(在调用点),如果您没有,那么您拥有完全相同的异常(在调用点)。您只需支付一些开销(并为原始代码添加一些模糊性)。如果这是一定不能发生的事情,那么我同意Patrick的观点:代码契约(或者,如果您以核心为目标,至少是断言)。“正如您所知,在方法中返回null会有一些问题”-哪一个会是?当然有“暗示”——但问题是什么?所以你用更糟糕的方法来规避它@Aria@Aria请注意,如果永远不允许使用
null
(并且您不能引入契约),那么您应该在假设的
NotNull
结构中进行一些检查(至少在创建值时,而不是在使用值时,您会得到一个异常(以后可能会以不明显的方式进行优化).@Fildor编辑的问题变成了暗示,谢谢。我的英语仍然很差。为什么不调用验证方法而不是创建结构?@AdrianoRepetti感谢您的努力和关注,但对我来说最大的好处是编译时,不要让方法返回空值。@Aria我想是的,这是您唯一可以满足的编译时要求n add是契约(但它们不会跨越WCF服务边界)。现在它们是你能做的最好的(AFAIK),然后是
契约。确保
是我想要的(编译时),如果消费者和服务处于不同的层,我的意思是我不希望服务的操作返回,你不能在那里使用相同的方法吗?如果我理解你,不,因为将来消费者可能是外部产品,而不是我们的。@Aria是服务还是消费者可能是第三方?那么我不明白问题所在。如果你确定在服务中,返回的项永远不会为null,然后在接口描述中说明。如果在必须返回null的情况下是错误/失败,则异常/错误结果是正确的方法。当然,这也必须在文档中说明。
public struct NotNullable<T> where T : class
{
    public NotNullable(T value)
    {
        Value = value ?? throw new ArgumentNullException(nameof(value));
    }

    public T Value { get; }
}
public static implicit operator T(NotNullable<T> rhs)
    => rhs.Value;
MyClass obj = Do();
obj.DoSomthing();
public SomeClass Do()
{
    MyClass somevalue = ...

    // ...

    return NotNull(somevalue);
}