Вопрос:

Enforcing method don't return null

c# oop null nullreferenceexception

112 просмотра

3 ответа

2810 Репутация автора

As question asked Here 8 years ago but I think there should be a way(New Patterns , New Designs , New Architectures or anything else.) to enforce method don't return null.

As you know there are some implications with returning null in a method one important for me is:

Handling null in Consuming-Side and understandable semantics like:

Method:

public ClassName Do()
{
    ...
    return null;
}

And calling Do() like (Attention Comments also):

var objVal = Do(); 
//Accessing property of ClassName raised exception
var pnVal = objVal.PropName;//Exception id objVal is null

//But I should handle if it is not null then do anything I want
if(objVal!= null)
{
    //Do something
}

after many problem on product by above way I came to this conclusion to generalize all method to follow a pattern to be readable,clean and preventing ambiguous semantic.

поэтому очень простой способ использует Structтип, потому что структура не может быть нулевой, если возвращаемый тип методов является структурой, то они не могут возвращать ноль, и мы знаем это во время компиляции, а не во время выполнения.

Так что я реализую этот метод выше, как:

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

Это structлучший способ? Стоит ли менять все методы и создавать DTO inи outдля каждого из них (я так думаю).

Есть ли лучший способ сделать это, любая идея, помощь, ответ был бы по достоинству оценен.

Автор: Aria Источник Размещён: 10.01.2018 08:39

Ответы (3)


3 плюса

131183 Репутация автора

Ваше преобразование «ссылочный тип» в «struct with property property» кажется мне бесполезным. Это также требует глубокого знания вашего намерения, в то время как проверка нулевого типа ссылки очевидна для всех, кто читает ее позже.

Я думаю, что контракты кода могут работать на вас. Он предоставляет вам статический анализ во время компиляции и проверки во время выполнения. Просто убедитесь, что у вас есть соответствующий контракт в качестве почтового условия:

public ClassName Do()
{
    ...

    object returnValue = null;

    Contract.Ensures(returnValue != null);

    return returnValue;
}
Автор: Patrick Hofman Размещён: 10.01.2018 08:46

1 плюс

51959 Репутация автора

Предполагая, что это значение никогда не может быть nullиначе, ifэто неизбежно (но для одного вызова метода теперь вы можете написать Do()?.DoSomething()).

Если вы можете ввести кодовые контракты (см . Ответ Патрика ), тогда я полностью согласен с Патриком, и вы должны согласиться с ними. Если это нежизнеспособно (потому что ваша кодовая база уже слишком велика или вы нацелены на среду, где они не поддерживаются), тогда я бы сначала использовал утверждения:

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

// Use obj...

Однако мы переносим эту ответственность на точку вызова, и это может быть утомительным. Если вы хотите сделать этот интерфейс явным, тогда вы можете использовать что-то такое, как вы думали, структуру, но выдает исключение в точке вызова (где ошибка):

public NotNullable<SomeClass> Do() { }

Где NotNullable<T>определяется как:

public struct NotNullable<T> where T : class
{
    public NotNullable(T value)
    {
        Value = value ?? throw new ArgumentNullException(nameof(value));
    }

    public T Value { get; }
}

Однако я не хотел бы явно обращаться .Valueк точке вызова, тогда я бы сделал это прозрачным добавлением:

public static implicit operator T(NotNullable<T> rhs)
    => rhs.Value;

Теперь звонящим может быть:

MyClass obj = Do();
obj.DoSomthing();

И правильное исключение выдается (во время выполнения, к сожалению) при создании объекта. Игра с [Conditional("DEBUG")]вами может исключить эту проверку для сборок релизов, имеющих поведение, аналогичное Debug.Assert()и минимальное (но все еще присутствующее) накладные расходы.

Обратите внимание, что это имеет смысл, только если вы хотите документировать метод интерфейса об этом ограничении непосредственно в его сигнатуре. Если вас это не интересует, сделайте это как можно проще:

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

    // ...

    return NotNull(somevalue);
}

Где NotNull()статический метод где-то определен и импортирован с помощью using staticили даже метода расширения для objectвызова as return somevalue.NotNull().

Мне не особенно нравится такой подход, потому что я думаю Debug.Assert(), что в этих случаях достаточно, но это только мое мнение. Конечно, может быть, когда-нибудь у нас будут Nullable Reference Types в C #, тогда мы получим принудительное исполнение во время компиляции (как object?и наоборот object!).

Автор: Adriano Repetti Размещён: 10.01.2018 08:59

0 плюса

186 Репутация автора

Возвращать null - плохая практика - лучше реализовать шаблон проектирования NullObject

Автор: Atul Jain Размещён: 06.05.2019 06:47
Вопросы из категории :
32x32