在string.Format()中分配引用值

时间:2016-04-19 09:44:16

标签: c# string performance

我有一个方法,它接受引用double并返回一个字符串,同时还修改引用的值:

const long OneKb = 1024;
const long OneMb = OneKb * 1024;
const long OneGb = OneMb * 1024;
const long OneTb = OneGb * 1024;

public string GetLargestDataSizeAndUnitOfMeasurement(ref double value, int decimalPlaces = 0)
{
    var asTb = Math.Round(value / OneTb, decimalPlaces);
    var asGb = Math.Round(value / OneGb, decimalPlaces);
    var asMb = Math.Round(value / OneMb, decimalPlaces);
    var asKb = Math.Round(value / OneKb, decimalPlaces);
    string unit = asTb > 1 ? string.Format("Tb", value = asTb)
    : asGb > 1 ? string.Format("Gb", value = asGb)
    : asMb > 1 ? string.Format("Mb", value = asMb)
    : asKb > 1 ? string.Format("Kb", value = asKb)
    : string.Format("B", value = Math.Round(value, decimalPlaces));
    return unit;
}

我的问题是,尽管该值与该方法本身无关,但是在string.Format()内为分配新值是否可以接受。如果我想避免这种情况,我可以单独执行if以修改value,但这看起来更清晰,并且可能在规模上更有效。

3 个答案:

答案 0 :(得分:1)

我真的看不出任何错误string.format方法中进行分配调用。但通过查看给定的代码,可以避免。

如果您要查找更干净的代码,可以使用枚举来存储数据单元名称,并且可以减少声明的变量。这样,您的代码更易于维护,如果您想要使用更高的数据大小单位,您只需将其添加到枚举列表

    public class DataSizeFormatter
    {
        const int OneKB = 1024;

        private enum DataSizes
        {
            B,
            KB,
            MB,
            GB,
            TB
        }

        public string GetLargestDataSizeAndUnitOfMeasurement(ref double value, int decimalPlaces = 0)
        {
            var highestExponent = (int)(Math.Log(value, OneKB));        // Get the highest power which you could assign to 1024 that would not be greater than the given value.
            var lengthOfDataSizeEnum = Enum.GetNames(typeof(DataSizes)).Length;     //Get the length of the enum list

            int highestExponentWithLimit = highestExponent < lengthOfDataSizeEnum ? highestExponent : lengthOfDataSizeEnum - 1;   //If the given value could be divided by a higher data unit than in your enum list then only use your highest data size unit.

            value = Math.Round(value / Math.Pow(OneKB, highestExponentWithLimit), decimalPlaces);   //round of your given value to the approriate data size.

            return ((DataSizes)highestExponentWithLimit).ToString();    //return the data size that was used to round of your given value.

        }
}

<强>更新

看看这些类似的问题,这些问题解释了为什么在参数范围内进行分配是好的: Variable assignment within method parameterWhy do assignment statements return a value?

更新2:

有关将字节转换为更高数据存储单元的最佳方法的问题已在此处得到解答: Does .NET provide an easy way convert bytes to KB, MB, GB, etc.?

答案 1 :(得分:0)

在String.Format()内部进行赋值value = asTb时有效。在可读性方面以及使用String.Format()的方式是意外行为。

MSDN docs说明了使用String.Format()的原因:

  

如果需要插入对象的值,请使用String.Format,   变量,或表达到另一个字符串

根据您的代码段,这不是您的意图。您只想返回格式化的文件大小及其对应的符号。

public class FileSizeConverter
{
    public enum FileSizeSymbol
    {
        B,
        KB,
        MB,
        GB,
        TB
    }

    public string FormatByteSize(ref double fileSize, int decimalPlaces = 0)
    {
        var unit = FileSizeSymbol.B;
        while (fileSize >= 1024 && unit < FileSizeSymbol.TB)
        {
            fileSize = fileSize / 1024;
            unit++;
        }

        fileSize = Math.Round(fileSize, decimalPlaces, MidpointRounding.AwayFromZero);

        return unit.ToString();
    }
}

答案 2 :(得分:-1)

创建一个具有Value和Unit属性的小类,一个ToString方法和一个以double作为参数的构造函数。也许称之为DimensionedNumber。

现在,您只需通过将值传递给构造函数来创建DimensionedNumber。如果要显示DimensionedNumber,可以使用ToString()方法。

这样的东西
public class DimensionedNumber
{
    public double Value{get; private set;}
    public string Dimension {get; private set;}

    const double OneKb = 1024.0;
    const double OneMb = OneKb * OneKb;
    const double OneGb = OneMb * OneKb;
    const double OneTb = OneGb * OneKb;

    public DimensionedNumber(double value)
    {
        if (value > OneTb) {
            Value = value / OneTb;
            Dimension = "Tb";
        } else if (value > OneGb) {
            Value = value / OneGb;
            Dimension = "Gb";
        } else if (value > OneMb) {
            Value = value / OneMb;
            Dimension = "Mb";
        } else if (value > OneKb) {
            Value = value / OneKb;
            Dimension = "Kb";
        } else {
            Value = value;
            Dimension = "";
        }
    }

    public string ToString(int decimalPlaces)
    {
        return Value.ToString("N" + decimalPlaces.ToString()) + Dimension;
    }
}

您可以将其与

一起使用
var displayValue = new DimenesionedNumber(12345678.9);
Console.WriteLine(displayValue.ToString(3));  // Three decimal places