C#, который я должен ПРОБОВАТЬ/ЛОВИТЬ для броска?

Если найдешь А, возвращайся рано. Если вы найдете B, сохраните его в переменной на случай, если вы не найдете As.

public Product getFirstAorB()
{
    Product firstB = null;
    for(Product product : productList) 
    {
        if ("A".equals(product.getName())) {
            return product;
        }
        else if (firstB == null && "B".equals(product.getName())) {
            firstB = product;
        }
    }
    return firstB;
}
9
задан Jon Skeet 10 January 2009 в 21:24
поделиться

8 ответов

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

(*) могут быть некоторые различия в терминах того, как JIT обрабатывает их. Первое закончится с большим количеством IL, который будет влиять на возможности для встраивания и т.д.

Править: Я не могу сопротивляться небольшому количеству микросравнительного тестирования. Похоже, что попытка/выгода/бросок имеет более противные эффекты на производительность, чем просто отключение встраивания:

using System;
using System.Diagnostics;
using System.Runtime.CompilerServices;

public class Test
{
    const int Iterations = 1000000000;

    static void Main()
    {
        Stopwatch sw;

        sw = Stopwatch.StartNew();
        for (int i=0; i < Iterations; i++)
        {
            SimpleMethod();
        }
        sw.Stop();
        Console.WriteLine("Simple method: {0}", sw.ElapsedMilliseconds);

        sw = Stopwatch.StartNew();
        for (int i=0; i < Iterations; i++)
        {
            NoInlining();
        }
        sw.Stop();
        Console.WriteLine("No inlining: {0}", sw.ElapsedMilliseconds);

        sw = Stopwatch.StartNew();
        for (int i=0; i < Iterations; i++)
        {
            TryCatchThrow();
        }
        sw.Stop();
        Console.WriteLine("try/catch/throw: {0}", sw.ElapsedMilliseconds);
    }

    static void SimpleMethod()
    {
        Foo();
    }

    [MethodImpl(MethodImplOptions.NoInlining)]
    static void NoInlining()
    {
    }

    static void TryCatchThrow()
    {
        try
        {
            Foo();
        }
        catch (Exception)
        {
            throw;
        }
    }

    static void Foo() {}
}

Скомпилируйте с /o+ /debug-

Результаты (три выполнения):

Простой метод: 504, 495, 489
Никакое встраивание: 2977, 3060, 3019
попытка/выгода/бросок: 5274, 4543, 5145

19
ответ дан 4 December 2019 в 08:35
поделиться

Эти два метода являются по существу тем же. В этом случае ReSharper был корректен со своим предложением.

1
ответ дан 4 December 2019 в 08:35
поделиться

Нет, Вам не нужна выгода попытки. Единственная причина Вы хотели бы использовать первую функцию, состоит в том, если Вы хотели сделать некоторый вход или высвободить средства прежде, чем обработать функцию далее.

3
ответ дан 4 December 2019 в 08:35
поделиться

Что-то, о чем я думал, но я не был уверен 100%, таким образом, я перешел к проверке. Я был прав, иногда.

По-видимому, если Вы повторно бросаете исключение, которое является тем, что делает Ваш код, Вы могли закончить тем, что изменили отслеживание стека. В первую очередь, если необходимо было записать throw ex; это сбросило бы отслеживание стека. Во-вторых, при записи throw; могут также быть случаи, где информация отсутствует. См. эту статью и некоторое развитие комментариев пользователей ее.

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

1
ответ дан 4 December 2019 в 08:35
поделиться

Они действительно не то же. Throw самостоятельно или throw ex путаница с информацией трассировки стека и может сделать отладку тяжелее.

Лучшая причина поймать исключение состоит в том, чтобы добавить контекст к отслеживанию стека, как:

try {
  Foo();
}
catch (Exception e) {
  throw new BetterException("I did something slightly silly", e);
}
1
ответ дан 4 December 2019 в 08:35
поделиться

ReSharper корректен. Если Вы на самом деле не намереваетесь поймать и сделать что-то об исключении нет никакого смысла включая попытку.. блок выгоды.

0
ответ дан 4 December 2019 в 08:35
поделиться

Да, блок выгоды попытки избыточен. Стек будет просто раскручен, пока попытка/выгода, как не находят, обрабатывает исключение.

0
ответ дан 4 December 2019 в 08:35
поделиться

Если все, что Вы делаете, повторно бросить исключение, Вам не нужен блок попытки/выгоды. Обычно необходимо только поймать исключения, когда можно обработать их. Иначе позвольте им распространить вверх.

0
ответ дан 4 December 2019 в 08:35
поделиться
Другие вопросы по тегам:

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