如果您使用的是 C# 3.0,则可以使用扩展方法和 IFormatProviders 更好地表达您的意图。在代码中,这可能是 FileInfo 和 DirectoryInfo ToString 方法的扩展方法,因此它们会读取如下内容:
var directorySize = myDirectory.ToString("GB");
var fileSize = myFile.ToString("MB");
上面的代码对于您正在尝试做的事情感觉更自然。
看看以下内容如何为您工作。其中一些需要测试(想到递归方法 DirectoryInfoExtender.GetDirectorySize)。如果您需要能够编写类似的语句Console.WriteLine("{0:GB}", fileInfo)
,您也可以考虑编写 IFormatProvider。
另请注意,对于这些可公开访问的方法,我有意省略了空值检查和异常处理。
public static class DirectoryInfoExtender
{
public static string ToString(this DirectoryInfo d, string format, int fractionalDigits)
{
double fileSize = GetDirectorySize(d);
return FileSizeConverter.GetFileSizeString(fileSize, format, fractionalDigits);
}
public static double GetDirectorySize(DirectoryInfo d)
{
var files = d.GetFiles();
var directories = d.GetDirectories();
if(files.Length == 0 && directories.Length == 0)
{
return 0;
}
else
{
double size = 0;
foreach(var file in files)
{
size += file.Length;
}
foreach(var directory in directories)
{
size += GetDirectorySize(directory);
}
}
return size;
}
}
public static class FileInfoExtender
{
public static string ToString(this FileInfo f, string format, int fractionalDigits)
{
return FileSizeConverter.GetFileSizeString(f.Length, format, fractionalDigits);
}
}
public class FileSizeConverter
{
public static string GetFileSizeString(double fileSize, string format, int fractionalDigits)
{
long divisor;
string sizeIndicator;
switch(format.ToLower().Trim())
{
case "gb":
divisor = (long)Math.Pow(2, 30);
sizeIndicator = "gigabytes";
break;
case "mb":
divisor = (long) Math.Pow(2, 20);
sizeIndicator = "megabytes";
break;
case "kb":
divisor = (long)Math.Pow(2, 10);
sizeIndicator = "kilobytes";
break;
default:
divisor = 1;
sizeIndicator = "bytes";
break;
}
return String.Format("{0:N" + fractionalDigits +"} {1}", fileSize / divisor, sizeIndicator);
}
}