2

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.

so a very basic Way is using Struct type because structure can't be null , if a return type of methods be structure then they can't return null and We know this in compile time not in runtime.

So I implement that above method like:

1- Make DTO out and in for method, in this case just 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- And Do method should be:

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

    }
    return Do_DTO_Out.Empty;
}

3- In consuming side:

var objVal = Do();
if (!objVal.IsEmpty)
    //Do something

Is struct is best way ? is it worth to change all method and create DTO in and out for each of them (I think so).

Is there better way to do that , any idea,help,answer would be truly appreciated.

Aria
  • 3,724
  • 1
  • 20
  • 51
  • What's the benefit over the original approach? You still need to explicitly call `IsEmpty`. It's nice that it follows the `Nullable` design but without a better compiler/runtime support we still are at the same point (waiting for the `ClassName!` C# syntax...). What you can do new now is `objVal?.DoSomething()` (when you need to _just_ call a single method). – Adriano Repetti Jan 10 '18 at 08:43
  • Seems like a lot of work for not much gain – TheGeneral Jan 10 '18 at 08:43
  • What about code contracts? https://learn.microsoft.com/en-us/dotnet/framework/debug-trace-profile/code-contracts – Patrick Hofman Jan 10 '18 at 08:44
  • @Saruman The best benefit of this is don't let method return null in `compile-time` as I mentioned. – Aria Jan 10 '18 at 08:44
  • 2
    @Aria method won't return `null` because it's returning a struct but it's still returning a struct with an empty reference, if you check for `IsEmpty` then you have the same code (at calling point), if you don't then you have exactly the same exception (at calling point). You just pay some overhead (and add some obscurity to original code). If it's something that must not happen then I agree with Patrick: code contracts (or, at least, assertions if you're targeting Core). – Adriano Repetti Jan 10 '18 at 08:46
  • 1
    "As you know there are some problems with returning null in a method" - which would be? There sure are "implications" - but _problems_ ? – Fildor Jan 10 '18 at 08:46
  • @Fildor See mentioned Link , Its inventor says it is a billion dollar mistake! – Aria Jan 10 '18 at 08:48
  • 1
    So you circumvent that with an even worse approach? @Aria – Patrick Hofman Jan 10 '18 at 08:48
  • 1
    @Aria Note that if `null` is NEVER allowed (and you can't introduce contracts) then you should put some checks in your hypothetical `NotNull` struct (at least you get an exception when value is created, not when it's used (which might be later and optimized in a non obvious way). – Adriano Repetti Jan 10 '18 at 08:53
  • Struct or Class are not different for me because everything will be serialized in WCF, Struct does not have any drawback. – Aria Jan 10 '18 at 09:10
  • 1
    @Fildor Edited problems changed to implications, thanks I still weak in English. – Aria Jan 10 '18 at 09:35
  • 1
    There is a preview of non-nullable reference types in C# [here](https://github.com/dotnet/csharplang/wiki/Nullable-Reference-Types-Preview). It will not break the execution, but will give warnings of possible nulls. Nice explanation of proposed behaviour and reasoning behind it [here](https://blogs.msdn.microsoft.com/dotnet/2017/11/15/nullable-reference-types-in-csharp/). – Justinas Marozas Jan 15 '18 at 14:29
  • @JustinasMarozas, Thank you. – Aria Jan 15 '18 at 14:31

3 Answers3

3

Your 'reference type' to 'struct with property check' conversion seems useless to me. It also requires intimate knowledge of your intention, while the reference type null check is very obvious to anyone reading it later.

I think code contracts could work for you. It provides you with compile time static analysis and runtime checks. Just make sure you have the appropriate contract as post condition:

public ClassName Do()
{
    ...

    object returnValue = null;

    Contract.Ensures(returnValue != null);

    return returnValue;
}
Patrick Hofman
  • 153,850
  • 22
  • 249
  • 325
  • Then `Contract.Ensures` is what I want (Compile Time), what about If consumer and service are in different layers , I mean I don't want service's operations return null – Aria Jan 10 '18 at 09:08
  • Can't you use the same methodology there? – Patrick Hofman Jan 10 '18 at 09:09
  • If I understand you, No, because in future consumer may be external product not ours. – Aria Jan 10 '18 at 09:14
  • Also contracts are inside service implementation and they're not visible (AFAIK) by static analyzer because it _sees_ just an interface. – Adriano Repetti Jan 10 '18 at 09:16
  • 1
    @Aria Is it the Service or the Consumer that could be 3rd party? – Fildor Jan 10 '18 at 09:19
  • @Fildor, All methods are implemented in WCF services and Consumer side may be WebApp,Mobile app,Client-Side, I sure in client-Side I never sent null object (even in rest). – Aria Jan 10 '18 at 09:32
  • 1
    Then I don't get the problem. If you ensure _in the service_ the returned item is never going to be null, then just state so in the interface description. If it is an error/failure in the case a null would have to be returned, an exception/error result is the correct way to go. This also must be stated in the docs, of course. – Fildor Jan 10 '18 at 09:37
1

Assuming that value can never be null otherwise the if is unavoidable (but for a single method call you can now write Do()?.DoSomething()).

If you can introduce code contracts (see Patrick's answer) then I completely agree with Patrick and you should go with them. If it's not viable (because your codebase is already too big or you're targeting an environment where they aren't supported) then I'd first use assertions:

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

// Use obj...

We're however moving this responsibility to calling point and it may be tedious. If you want to make this interface explicit then you can use something a struct as you thought but throwing an exception at calling point (where the error is):

public NotNullable<SomeClass> Do() { }

Where NotNullable<T> is defined as:

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

    public T Value { get; }
}

However I do not like to explicitly access .Value at calling point then I'd make it transparent adding:

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

Now caller can be:

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

And the proper exception is thrown (at run-time, unfortunately) when object is created. Playing with [Conditional("DEBUG")] you may exclude that check for release builds having then a behavior similar to Debug.Assert() and a minimal (but still present) overhead.

Note that this makes sense only if you want to document interface method about this constraint directly in its signature. If you're not interested in this then keep it as simple as possible:

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

    // ...

    return NotNull(somevalue);
}

Where NotNull() is a static method define somewhere and imported with using static or even an extension method for object called as return somevalue.NotNull().

I don't especially like this approach because I think Debug.Assert() is enough in these cases but it's just my opinion. Of course maybe someday we will have Nullable Reference Types in C# then we'll get compile-time enforcement (as object? or the other way round object!).

Adriano Repetti
  • 65,416
  • 20
  • 137
  • 208
  • Why not just call a validation method instead of creating a struct? – Patrick Hofman Jan 10 '18 at 09:00
  • @AdrianoRepetti Thank you for your effort and attention, but the large benefit for me is compile-time and don't letting methods return null. – Aria Jan 10 '18 at 09:30
  • @Aria I supposed so, the only compile-time requirement you can add are contracts (but they don't play across WCF service boundaries). Nowadays they're best you can do (AFAIK) – Adriano Repetti Jan 10 '18 at 09:35
0

Returning null is a bad practice - better to implement NullObject Design Pattern

Atul Jain
  • 1,035
  • 2
  • 16
  • 24