2016-04-19 16 views
1

Ich habe ein Verfahren, das in einem Doppel Referenz nimmt und gibt eine Zeichenfolge, während auch den Wert der Referenz modifizierende:Zuweisen Referenzen Werte innerhalb string.Format()

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; 
} 

Meine Frage ist, ob es annehmbar Weisen Sie der Referenz einen neuen Wert innerhalb der string.Format() zu, obwohl der Wert für diese Methode nicht relevant ist. Ich könnte die if separat ausführen, um value zu ändern, wenn ich dies vermeiden wollte, aber dies scheint sauberer und potenziell effizienter im Maßstab.

+0

'string.Format (" Tb ", Wert = asTb)' dies wird "Tb" zurückgeben. Warum verwenden Sie überhaupt Format? Und das sieht nicht sauberer aus. Es ist hässlich und verwirrend. –

+0

@GiorgiNakeuri das ist meine Frage, die 'string.Format()' erlaubt mir, die Referenz inline zu aktualisieren, während auch die Zeichenfolge, die ich brauche. Ich will nur wissen, ob das verpönt ist oder nicht, und warum. –

+0

Zuweisung ist ein ** gültiger ** C# Ausdruck, und da Sie ein ** gültiges ** C# Konstrukt verwenden, warum sollte es nicht akzeptabel sein? –

Antwort

-1

Erstellen Sie eine kleine Klasse mit Value- und Unit-Eigenschaften, eine ToString-Methode und einen Konstruktor, der ein Double als Parameter verwendet. Vielleicht nennen Sie es DimensionedNumber.

Jetzt erstellen Sie einfach eine DimensionedNumber, indem Sie den Wert an den Konstruktor übergeben. Wenn Sie die DimensionedNumber anzeigen möchten, können Sie einfach die ToString() -Methode verwenden.

So etwas wie

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; 
    } 
} 

Sie es mit

var displayValue = new DimenesionedNumber(12345678.9); 
Console.WriteLine(displayValue.ToString(3)); // Three decimal places 
1

verwenden würde ich wirklich sehe nichts falsch mit innerhalb einer string.format Methodenzuordnung Anrufe zu tun. Aber wenn man sich den gegebenen Code anschaut, könnte man das vermeiden.

Wenn Sie saubereren Code suchen, könnte Sie ein ENUM verwenden Ihre Dateneinheit zum Speichern von Namen und man konnte die Menge der Variablen reduzieren Sie deklarieren. Auf diese Weise ist Ihr Code mehr wartbar und wenn Sie jemals eine höhere Datengröße Einheit verwenden möchten, könnten Sie nur hinzufügen, um Enum-Liste.

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. 

     } 
} 

UPDATE:

Haben Sie einen Blick auf diesen ähnlichen Fragen, die erklärt, warum es in Ordnung Zuweisungen innerhalb von Parametern zu tun: Variable assignment within method parameter und Why do assignment statements return a value?.

UPDATE 2:

Die Frage um einen besten Ansatz, um Bytes zu höheren Datenspeichereinheiten Umwandlung hat hier beantwortet: Does .NET provide an easy way convert bytes to KB, MB, GB, etc.?.

0

Während eine Zuweisung, value = asTb, innerhalb einer String.Format() gültig ist. In Bezug auf die Lesbarkeit und Art, in der String.Format() verwendet wird, ist unerwartetes Verhalten.

MSDN docs Staaten der Grund für die Verwendung von String.Format() als:

Verwenden String.Format, wenn Sie den Wert eines Objekts, Variable oder ein Ausdruck in eine andere Zeichenfolge

Base auf Ihr Code-Snippet eingefügt werden müssen, ist dies nicht Ihre Absicht. Sie möchten lediglich eine formatierte Dateigröße und das entsprechende Symbol zurückgeben.

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(); 
    } 
}