1

I want to return a empty string when the SomethingName is null. plants.Something.Name != null ? plants.Something.Name : string.Empty still gets me a null pointer. I have debugged my application to know this is causing a NullPointerException.

When I set data in the database for SomethingName, I dont get a null pointer exception.

Is there a better way to handle this?

    public FlowerMetaData GetLeafByFlowerId(int flowerId, string flowerName)
    {
        _flowerContext = _contextUtility.GetFlowerContext(flowerName);

        var flowerData = (from flowers in _flowerContext.Flowers
                            where flowers.FlowerId == flowerId
                            join plants in _flowerContext.Plants on flowers.PlantId equals plants.PlantId
                            join leafs in _flowerContext.Leafs on flowers.LeafAk equals leafs.LeafAK
                            select new FlowerMetaData
                            {
                                PlantId = plants.PlantId,
                                PlantName = plants.PlantName,
                                FlowerName = FlowerName.ToUpper(),
                                FlowerNumber = leafs.FlowerNumber,
                                SomethingName = plants.Something.Name != null ? plants.Something.Name : string.Empty,
                                CreatedId = plants.CreatedId,
                            }).FirstOrDefault();

        return flowerData;
    }

StackTrace

    "Message": "An error has occurred.",
    "ExceptionMessage": "No flower found with id = 37.",
    "ExceptionType": "System.NullReferenceException",
    "StackTrace": "   at Flower.Services.FlowerService.GetLeafByFlowerId(Int32 flowerId, String flowerName)
at Flower.Controllers.Controllers.FlowerController.GetFlower(Int32 id, String client)\r\n   at lambda_method(Closure , Object , Object[] )
at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ActionExecutor.<>c__DisplayClass10.<GetExecutor>b__9(Object instance, Object[] methodParameters) at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ExecuteAsync(HttpControllerContext controllerContext, IDictionary`2 arguments, CancellationToken cancellationToken)
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()\r\n   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n   at System.Web.Http.Controllers.ApiControllerActionInvoker.<InvokeActionAsyncCore>d__0.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
 at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n   at System.Web.Http.Controllers.ActionFilterResult.<ExecuteAsync>d__2.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
  at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n   at System.Web.Http.Filters.AuthorizationFilterAttribute.<ExecuteAuthorizationFilterAsyncCore>d__2.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
  at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
  at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
  at Sentinel.Services.AuthFilters.AddChallengeOnUnauthorizedResult.<ExecuteAsync>d__7.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
  at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n   at System.Web.Http.Controllers.AuthenticationFilterResult.<ExecuteAsync>d__0.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()\r\n   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n   at System.Web.Http.Dispatcher.HttpControllerDispatcher.<SendAsync>d__1.MoveNext()"
}
7
  • 2
    SomethingName = plants.Something.Name ?? string.Empty Commented Apr 4, 2018 at 17:38
  • 1
    @Vache C# has moved on since that post Commented Apr 4, 2018 at 17:47
  • 1
    @PeterSmith But not with the way you identity the source of NRE. Commented Apr 4, 2018 at 18:29
  • If you could provide the stack trace you're seeing, that would help a lot in determining whether this is a "normal" NRE or not. Commented Apr 4, 2018 at 18:30
  • @DaisyShipton, I added the stack trace, not sure it it will help, but thank you. Commented Apr 4, 2018 at 18:58

2 Answers 2

4

Usually you can use the null-conditional operator from C# 6, combined with the null-coalescing operator from C# 2 to make this really easy:

SomethingName = plants.Something?.Name ?? ""

The expression plants.Something?.Name will evaluate to null (rather than throwing an exception) if plants.Something evaluates to null. The ?? "" part then just says "If the result of the expression is null, use the empty string instead."

If plants itself could be null, you could use:

SomethingName = plants?.Something?.Name ?? ""

... but in this case you shouldn't need to.

However, there's a wrinkle: if you're doing this in an LINQ provider that uses IQueryable<T> (rather than IEnumerable<T> as LINQ to Objects usually does), each part of your query expression will be converted into an expression tree, and the null-conditional operator isn't supported in expression trees. As such, you may need to perform a projection in the query, then do the last part in-process. For example:

var entry = (from flowers in _flowerContext.Flowers
             where flowers.FlowerId == flowerId
             join plants in _flowerContext.Plants on flowers.PlantId equals plants.PlantId
             join leafs in _flowerContext.Leafs on flowers.LeafAk equals leafs.LeafAK
             select new { plants, leafs }).FirstOrDefault();
return entry == null 
    ? null // No entry in the database
    : new FlowerMetaData
      {
          PlantId = entry.plants.PlantId,
          PlantName = entry.plants.PlantName,
          FlowerName = FlowerName.ToUpper(),
          FlowerNumber = entry.leafs.FlowerNumber,
          SomethingName = entry.plants.Something?.Name ?? "",
          CreatedId = entry.plants.CreatedId,
       };
Sign up to request clarification or add additional context in comments.

17 Comments

what can I do if plant or something is not nullable.
@Maddy: Then the compiler won't allow you to use ?., but you wouldn't get a NullReferenceException anyway for that part, because you couldn't be dereferencing a null value.
?. operator cannot be used in expression trees though.
@IvanStoev: You're absolutely right. Will edit.
@IvanStoev: Have a look now.
|
1

Not tested but

SomethingName = plants.Something?.Name ?? string.empty

should do what's required. What Daisy said!

3 Comments

What can I do if Something is not nullable?
@Maddy: Then Something.Name shouldn't throw a NullReferenceException.
Daisy has it all covered!

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.