What needs to be returned if not null when the value cannot be found

Everywhere I read, the idea of ​​never returning zeros is constantly repeated, but what should I return, if not null, in cases where the value cannot be found?

Take the following method

List<Customer> GetCustomerListByRoleID(Guid RoleID) {} 

In this case (and in most plural methods) it is easy to just return an empty List<Customer> if we cannot find our value, and we are good.

However, in the case of a method of type

 Customer GetCustomerByID(Guid CustomerID) {} 

You do not have the luxury of returning an empty array. Infact all you can do is return New Customer(); but then you have a potentially uninitialized object (which you still need to check) or null.

So, what would be the recommended alternative to returning null in a singular method?

+4
source share
4 answers

For a single-value case, consider the TryGet pattern TryGet

 bool TryGetCustomerByID(Guid CustomerID, out Customer customer) { } 

This clearly expresses the intention that this method may fail, and makes it more inconvenient to ignore the aspect of failure. By dealing with this correctly, you get very readable code.

 Customer c; if (container.TryGetCustomer(id, out c)) { ... } else { // Deal with failure } 

Often I like to connect my TryGet APIs with a version that throws those cases when the caller knows that he must be present, otherwise this is a violation of some implicit contract.

 Customer GetCustomerByID(Guid id) { Customer c; if (!TryGetCustomerByID(id, out c)) { throw new Exception(...); } return c; } 
+10
source

I think it depends on whether to consider the fact that the request for the client does not exist. Two obvious options:

  • Return null
  • Throw an exception ( CustomerNotFoundException or something like that)

When you are assigned a Guid , you get the feeling that this will represent the client. It doesn't seem like it would be normal to try to pull the client using Guid , if one exists.

You can return Tuple<Customer, bool> or TryGetCustomer , but to be honest, I think they are too complicated for these purposes.

Most importantly, you are documenting what will happen ... in particular, if your code never returns null, specify this in the documentation. (Or consider using code contracts to get the same information ...)

0
source

You can define a static Customer object that represents a null customer (that is, Customer.Name = "NOT_FOUND" and return this object instead of null. Then, in the calling method, simply compare the return value with this static client.

edit: Although I admittedly will soon return null.

0
source

Why is a null reconfiguration not recommended? The idea is that if the return type of the function is T , you always get one object of type T , and null definitely not something of type T , even null objects of type T

In the case of getCustomers() you get a List<Customer> , from 0 to n Customer objects.

In the case of getCustomer() you need 0 or 1 Customer objects. In Haskell, you get ADT and Maybe for this, in Scala you have the case and Option classes. What can you use in c #? Well, there Maybe the implementation is in C # , it's really just inside.

With Maybe<Customer> getCustomer() you are guaranteed not to pass its result as a null value instead of a Customer value. You are clearly warned: you can get the Client or not the Client.

Why Maybe works better than null ? Because Maybe is a monad with a sound mathematical foundation, and null is not. List also a monad, which makes it so convenient. With the right approach, monads can be combined beautifully , so you don't need to check HasValue everywhere. With null you are stuck in a nested C if style for each function result.

Exceptions are also a monad! This is why the other answers (correctly) suggest throwing an exception. With exceptions, you even get another nice thing that is characteristic of functional programming, namely pattern matching (in catch ).

0
source

Source: https://habr.com/ru/post/1399564/


All Articles