Номер PHP: десятичная точка видна только при необходимости

Ответ ниже строки был записан в 2008.

C# 7 представил сопоставление с образцом, которое в основном заменило as оператор, как можно теперь записать:

if (randomObject is TargetType tt)
{
    // Use tt here
}

Отметьте это tt находится все еще в объеме после этого но не определенно присвоен. (Это определенно присвоено в if тело.) Это является немного раздражающим в некоторых случаях, поэтому если Вы действительно заботитесь о представлении самого маленького количества переменных, возможных в каждом объеме, Вы могли бы все еще хотеть использовать is сопровождаемый броском.


Я не думаю ни один из ответов до сих пор (во время запуска этого ответа!) действительно объяснили, где это стоит использовать который.

  • Не делайте этого:

    // Bad code - checks type twice for no reason
    if (randomObject is TargetType)
    {
        TargetType foo = (TargetType) randomObject;
        // Do something with foo
    }
    

    Мало того, что это проверяет дважды, но и это может проверять разные вещи, если randomObject поле, а не локальная переменная. Для возможно, "если" передать, но затем бросок для сбоя, если другой поток изменяет значение randomObject между двумя.

  • Если randomObject действительно должен быть экземпляр TargetType, т.е. если это не, который означает, что существует ошибка, затем кастинг является правильным решением. Это сразу выдает исключение, что означает, что больше работы не сделано под неправильными предположениями, и исключение правильно показывает тип ошибки.

    // This will throw an exception if randomObject is non-null and
    // refers to an object of an incompatible type. The cast is
    // the best code if that's the behaviour you want.
    TargetType convertedRandomObject = (TargetType) randomObject;
    
  • Если randomObject мог бы быть экземпляр TargetType и TargetType ссылочный тип, затем используйте код как это:

    TargetType convertedRandomObject = randomObject as TargetType;
    if (convertedRandomObject != null)
    {
        // Do stuff with convertedRandomObject
    }
    
  • Если randomObject мог бы быть экземпляр TargetType и TargetType тип значения, затем мы не можем использовать as с TargetType самостоятельно, но мы можем использовать nullable тип:

    TargetType? convertedRandomObject = randomObject as TargetType?;
    if (convertedRandomObject != null)
    {
        // Do stuff with convertedRandomObject.Value
    }
    

    (Примечание: в настоящее время это на самом деле медленнее, чем + бросок. Я думаю, что это более изящно и последовательно, но там мы идем.)

  • Если Вам действительно не нужно преобразованное значение, но просто необходимо знать, является ли это экземпляром TargetType, то is оператор является Вашим другом. В этом случае не имеет значения, является ли TargetType ссылочным типом или типом значения.

  • Могут быть другие случаи, включающие дженерики где is полезно (потому что Вы не можете знать, является ли T ссылочным типом или нет, таким образом, Вы не можете использовать в качестве), но они относительно неясны.

  • Я почти наверняка использовал is поскольку значение вводит случай до настоящего времени, не думая об использовании nullable типа и as вместе :)


Править: Обратите внимание, что ни одни из вышеупомянутых переговоров о производительности, кроме значения не вводят случай, где я отметил, что распаковывание к nullable типу значения на самом деле медленнее - но последовательно.

Согласно ответу naasking,-и-бросать или, и как оба с такой скоростью, как as-and-null-check с современными МОНЕТАМИ В ПЯТЬ ЦЕНТОВ, как показано кодом ниже:

using System;
using System.Diagnostics;
using System.Linq;

class Test
{
    const int Size = 30000000;

    static void Main()
    {
        object[] values = new object[Size];
        for (int i = 0; i < Size - 2; i += 3)
        {
            values[i] = null;
            values[i + 1] = "x";
            values[i + 2] = new object();
        }
        FindLengthWithIsAndCast(values);
        FindLengthWithIsAndAs(values);
        FindLengthWithAsAndNullCheck(values);
    }

    static void FindLengthWithIsAndCast(object[] values)        
    {
        Stopwatch sw = Stopwatch.StartNew();
        int len = 0;
        foreach (object o in values)
        {
            if (o is string)
            {
                string a = (string) o;
                len += a.Length;
            }
        }
        sw.Stop();
        Console.WriteLine("Is and Cast: {0} : {1}", len,
                          (long)sw.ElapsedMilliseconds);
    }

    static void FindLengthWithIsAndAs(object[] values)        
    {
        Stopwatch sw = Stopwatch.StartNew();
        int len = 0;
        foreach (object o in values)
        {
            if (o is string)
            {
                string a = o as string;
                len += a.Length;
            }
        }
        sw.Stop();
        Console.WriteLine("Is and As: {0} : {1}", len,
                          (long)sw.ElapsedMilliseconds);
    }

    static void FindLengthWithAsAndNullCheck(object[] values)        
    {
        Stopwatch sw = Stopwatch.StartNew();
        int len = 0;
        foreach (object o in values)
        {
            string a = o as string;
            if (a != null)
            {
                len += a.Length;
            }
        }
        sw.Stop();
        Console.WriteLine("As and null check: {0} : {1}", len,
                          (long)sw.ElapsedMilliseconds);
    }
}

На моем ноутбуке они все выполняются приблизительно в 60 мс. Две вещи отметить:

  • Нет никакой значительной разницы между ними. (На самом деле существуют ситуации, в которых as-plus-null-check определенно медленнее. Вышеупомянутый код на самом деле осуществляет проверку типа, легкую, потому что это для запечатанного класса; если Вы проверяете на интерфейс, подсказки по балансу немного в пользу as-plus-null-check.)
  • Они все безумно быстры. Это просто не будет узким местом в Вашем коде, если Вы действительно не соберетесь делать что-либо со значениями впоследствии.

Поэтому давайте не волноваться о производительности. Давайте волноваться о правильности и непротиворечивости.

Я поддерживаю, что-и-бросать (или и как) оба небезопасны при контакте с переменными, поскольку тип значения, к которому он относится, может измениться из-за другого потока между тестом и броском. Это было бы довольно редкой ситуацией - но у меня скорее будет конвенция, которую я могу последовательно использовать.

Я также поддерживаю, что as-then-null-check дает лучшее разделение проблем. У нас есть один оператор, который делает попытку преобразования и затем одного оператора, который использует результат.-И-бросать или и как выполняет тест и затем другую попытку преобразовать значение.

Другими словами, был бы любой когда-либо писать:

int value;
if (int.TryParse(text, out value))
{
    value = int.Parse(text);
    // Use value
}

Это - вид того, что-и-бросать делает - хотя, очевидно, скорее более дешевым способом.

57
задан vitto 6 November 2010 в 14:49
поделиться

1 ответ

Мои начиная с большей части количества или частей не требуют десятичного числа, эта функция только покажет десятичное число при необходимости.

str_replace(".00", "", number_format($this->pieces, 2));
0
ответ дан 24 November 2019 в 19:45
поделиться
Другие вопросы по тегам:

Похожие вопросы: