Reputation: 63778
string o=null;
Console.WriteLine($"Hello World '{o}'");
This outputs:
Hello World ''
I would like to explicitly write "null" for null values.
string o=null;
Console.WriteLine($"Hello World '{o??"null"}'");
This does just that:
Hello World 'null'
But if o
is not of type string
(or Object
) it generates a compilation error. For example:
Array o=null;
Console.WriteLine($"Hello World '{o??"null"}'");
Compilation error Operator '??' cannot be applied to operands of type 'Array' and 'string'
What is the best way to achieve the desired outcome? It's a shame you cannot modify how $
handles null
as it appears hard-coded to use String.EmptyString
Upvotes: 2
Views: 1843
Reputation: 6364
I'm not sure what you want to print if your variable is not null, but you could try the ternary conditional operator
Array o = null;
Console.WriteLine($"Hello World '{(o == null ? "null" : "not null")}'");
or
Array o = null;
Console.WriteLine($"Hello World '{(o == null ? "null" : o.ToString())}'");
depending on what o
is and whether you have overridden ToString()
.
Related:
How to print the null values if the dictionary has it using LINQ
Upvotes: 0
Reputation: 74660
You can leverage that $ can turn your string into a formattablestring and you can provider a custom formatted that it will call when it processes each arg in turn. Like providing a custom comparer to a sort function
class NullyFormatProvider : IFormatProvider
{
private readonly NullyFormatter _formatter = new NullyFormatter();
public object GetFormat(Type formatType)
{
if (formatType == typeof(ICustomFormatter))
return _formatter;
return null;
}
class NullyFormatter : ICustomFormatter
{
public string Format(string format, object arg, IFormatProvider formatProvider)
{
if (arg == null)
return "arg was null, bro!";
else
return arg.ToString();
}
}
}
You can trigger your null format provider by passing it through a function that will make c# treat it as a formattable string (rather than the compiler straight calling string format on it for example) :
static string NullyVersion(FormattableString formattable)
{
return formattable.ToString(new NullyFormatProvider());
}
...
Array o = null;
string txt = NullyVersion($"check out this array: {o}");
Of course, you wouldn't make it this lengthy/you probably wouldn't use NullyVersion to create a string to use where you wanted a string.. you'd make your e.g. "logging method that takes a string" take a FormattableString instead and then format it with the nully formatter perhaps like:
static string Log(FormattableString formattable)
{
Console.WriteLine( formattable.ToString(new NullyFormatProvider()); //or some instance of NFP
}
Then you can just use in your code like you wanted at the outset:
Array o = null;
Log($"Data was {o}");
I haven't looked too deep into how to check whether you're passed something that takes a format - you'll note that the Format() method in the ICustomFormatter takes a string format
- if you wrote Log($"it is now {DateTime.Now:yyyyMMdd} woo")
then the object arg
would be the datetime, and the string format
would contain "yyyyMMdd"
- it can be anything you want. You could define your own:
int[] nums = {1,2,3};
Log($"those nums are {nums:csv}");
And in your Format:
if(format == "csv" && arg is int[] x)
//turn the passed in arg (an int array inside an obj) into some csv representation...
return string.Join(",", x.Select(e => e.ToString()));
For more details take a look at ICustomFormatter https://learn.microsoft.com/en-us/dotnet/api/system.icustomformatter?view=netcore-3.1
Upvotes: 4
Reputation: 17095
You can cast "null"
to object
so that ??
can be applied to all types of operands.
$"Hello World '{o ?? (object)"null"}'"
Upvotes: 8