简体   繁体   中英

LINQ: Null checking in string.Format()

I have a requirement to get the first letter of the first, middle and last names. It is working if each of the fields contain value. But the middle name is nullable field. So i'm getting error if the value of middle name is null.

(from P in this._dbContext.Person
                     where P.PersonIndex == personIndex
                     select new PersonInitialsDTO
                     {
                         PersonIndex = P.PersonIndex,
                         PersonInitials = string.Format("{0}{1}{2}", P.FirstName.ToUpper().First(), P.MiddleName.ToUpper().First(), P.LastName.ToUpper().First())
                     }).FirstOrDefault();      

use ? to see if the value is null before executing next methods.

string.Format("{0}{1}{2}", P.FirstName.ToUpper().First(), P.MiddleName?.ToUpper().First(), P.LastName.ToUpper().First())

P.MiddleName?.ToUpper().First() -> If P.MiddleName is null, dont do ToUpper() or any other methods afterwards.


Example of use of?. in string.format statement .

Pers person = new Pers()
{
    First = "First",
    Last = "Last"
};
Console.WriteLine(string.Format("{0}{1}{2}", person.First.First(), person.Middle?.ToUpper().First(), person.Last.First()));

// Prints
FL

Requirement : get the first letter of the first, middle and last names.

Well, apparently this requirement is not complete: if one of these names is null or empty, there is no first letter.

Furthermore: if I look at the code, you don't want the first letter, you want a string that contains the first letter.

And why uppercase the complete string if you will only use the first character?

So let's change it slightly:

Requirement : Given three strings: first, middle and last, get me the string that contains the uppercase values of the first character of each of these strings, or String.Empty if the string is null or empty.

  • "Vincent" "van" "Gogh" => "VVG"
  • "rembrandt" "van" "rijn" => "RVR"
  • "Piet" "Mondriaan" => "PM"

From each of these three strings,

  • Check if if it is null, if so, use Enumerable.Empty<char>
  • Create a sequence that contains only the first character of the string. So if the string was null or empty, this first character will be an empty sequence of character).
  • Concatenate these three sequences.

Result: a sequence of characters that contains only the first character of each of these strings, or no character at all if the string was null or empty.

In baby steps, I'll write the type in front, so you can see what happens.

string first = ...
string middle = ...
string last = ...
IEnumerable<char> firstChars = first?.Take(1) ?? Enumerable.Empty<char>(),
IEnumerable<char> midChars = middle?.Take(1) ?? Enumerable.Empty<char>(),
IEnumerable<char> lastChars = last?.Take(1) ?? Enumerable.Empty<char>(),
IEnumerable<char> chars = firstChars.Concat(midChars).Concat(lastChars);

So from our original input examples we have:

  • Vincent Van Gogh: {'V', 'V', 'G'}
  • rembrandt van rijn: {'r', 'v', 'r'}
  • Piet Mondriaan {'p', 'm'}

So all we have to do is to convert them to uppercase and convert to a string:

IEnumerable uppercaseChars = chars.Select(c => Char.ToUpper(c));

Note: until know the query is not executed! I only used methods that use deferred execution!

string result = new string(uppercaseChars.ToArray());

Of course you can write this in one big LINQ statement. I'm not sure if that would improve readability. It won't have any effect on performance.

I tried with below. Now it's working

(from P in this._dbContext.Person
    where P.PersonIndex == personIndex
    select new PersonInitialsDTO
    {
        PersonIndex = P.PersonIndex,
        PersonInitials = (P.MiddleName == "") 
            ? string.Format("{0}{1}", P.FirstName.ToUpper().First(), 
                P.LastName.ToUpper().First()) 
            : string.Format("{0}{1}{2}", P.FirstName.ToUpper().First(), 
                P.MiddleName.ToUpper().First(), P.LastName.ToUpper().First())
    }).FirstOrDefault();   

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM