Gawd but I hate the way MS changed null handling...
-
A chunk of code:
string[] files = Directory.GetFiles(@"D:\Test data\Invoices"); foreach (string oldPath in files) { string oldName = Path.GetFileNameWithoutExtension(oldPath); string[] parts = oldName.Split(" - "); int id = int.Parse(parts[0].Substring(parts[0].Length - 3)); string newName = $"Invoice {id:000} - {parts[1]}"; string newPath = Path.Combine(Path.GetDirectoryName(oldPath), oldPath.Replace(oldName, newName)); if (oldPath != newPath) { System.IO.File.Move(oldPath, newPath); } }
It's not pretty, but it's a one off run to change demo file names to include leading zeros:
Invoice 1 - Customer name.inv
becomes
Invoice 001 - Customer name/inv
And MS doesn't like it, I get a warning:
Possible null reference argument for parameter 'path1' in 'string Path.Combine(string path1, string path2)'.
But ... and this is the really stupid bit ... I know it's never null, AND SO DOES THE COMPILER! How can I tell? If I hover over oldPath I get "oldPath is not null here"! But it still gives me a green squiggle and a warning message.
Yes, I can use #pragma to disable and restore the warning, but ... Stupid, stupid ...
-
It's not moaning about
oldPath
; it's moaning about the first parameter, which is the return value ofPath.GetDirectoryName(oldPath)
.Looking at the source, that method is declared as returning
string?
, notstring
. The documenation says:The returned value is null if the specified path is null, empty, or a root (such as
"\"
,"C:"
, or"\\server\share"
).In this instance, since you know that's not the case, you can suppress the warning with the "damnit" (or "Janet Weiss") operator:
string newPath = Path.Combine(Path.GetDirectoryName(oldPath)!, oldPath.Replace(oldName, newName));
However, since you're not looking at subdirectories, you know that all files will be in the same directory. So wouldn't it make sense to pass in the known directory instead?
string newPath = Path.Combine(@"D:\Test data\Invoices", ...
Also, I don't think that
Path.Combine
is really doing what you think. You're passing in a full path as the second parameter, so the first parameter will effectively be ignored. I suspect you meant to passnewName
as the second parameter, rather thanoldPath.Replace(oldName, newName)
:string newPath = Path.Combine(@"D:\Test data\Invoices", newName);