It's easy to turn some of the answers in to a helper extension class with generics for a even broader usage:
NOTE: for an explanation of short-circuit method the see the wensveen answer
// classic
public static string Coalesce(this string s, params string[] strings)
  => s.Coalesce(string.IsNullOrEmpty, strings);
// short-circuit compatible, for expensive string getting
public static string Coalesce(this string s, params Func<string>[] getters)
  => s.Coalesce(string.IsNullOrEmpty, getters);
// generic
public static T Coalesce<T>(this T value, Func<T, bool> isEmpty, params T[] values) where T : class
  => isEmpty(value) ? values.FirstOrDefault(val => !isEmpty(val)) : value;
// generic, short-circuit compatible
public static T Coalesce<T>(this T value, Func<T, bool> isEmpty, params Func<T>[] getters) where T : class {
  if (isEmpty(value))
    return getters
      .Select(getter => new Lazy<T>(getter))
      .FirstOrDefault(val => !isEmpty(val.Value))
      ?.Value;
  return value;
}
Example usage:
string result = s.SiteNumber.Coalesce(s.AltSiteNumber, "No Number");
string result = s.SiteNumber.Coalesce(string.IsNullOrWhiteSpace, s.AltSiteNumber, "No Number");
string navigationTitle = model?.NavigationTitle.
  Coalesce(() => RemoteTitleLookup(model?.ID), () => model?.DisplayName);
Player player = player1.Coalesce(p => p?.Score > 0, player2, player3);
(PS: I think I'm getting bit off topic here using generics. Am I overthinking this?)