Если найдешь А, возвращайся рано. Если вы найдете 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;
}
Да, те методы в значительной степени (*) то же. Единственная разница - то, что легко поместить точку останова в первую. Я всегда шел бы со вторым, если я действительно не должен был повреждаться там, и только там (в противоположность сразу любым исключениям того типа были брошены, который будет легок). Даже если я когда-нибудь использовал первое, я отложил его к второй форме прежде, чем фиксировать код.
(*) могут быть некоторые различия в терминах того, как 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
Эти два метода являются по существу тем же. В этом случае ReSharper был корректен со своим предложением.
Нет, Вам не нужна выгода попытки. Единственная причина Вы хотели бы использовать первую функцию, состоит в том, если Вы хотели сделать некоторый вход или высвободить средства прежде, чем обработать функцию далее.
Что-то, о чем я думал, но я не был уверен 100%, таким образом, я перешел к проверке. Я был прав, иногда.
По-видимому, если Вы повторно бросаете исключение, которое является тем, что делает Ваш код, Вы могли закончить тем, что изменили отслеживание стека. В первую очередь, если необходимо было записать throw ex;
это сбросило бы отслеживание стека. Во-вторых, при записи throw;
могут также быть случаи, где информация отсутствует. См. эту статью и некоторое развитие комментариев пользователей ее.
Конечно, большинство этих проблем связано с отслеживанием стека и номерами строки, которые важны, но я думал, что оно будет также влиять на производительность, не только из-за встраивания (или отсутствие этого), но также и из-за целой ловли исключения и броска наверху, но я ничто не нашел конкретным на этом.
Они действительно не то же. Throw
самостоятельно или throw ex
путаница с информацией трассировки стека и может сделать отладку тяжелее.
Лучшая причина поймать исключение состоит в том, чтобы добавить контекст к отслеживанию стека, как:
try {
Foo();
}
catch (Exception e) {
throw new BetterException("I did something slightly silly", e);
}
ReSharper корректен. Если Вы на самом деле не намереваетесь поймать и сделать что-то об исключении нет никакого смысла включая попытку.. блок выгоды.
Да, блок выгоды попытки избыточен. Стек будет просто раскручен, пока попытка/выгода, как не находят, обрабатывает исключение.
Если все, что Вы делаете, повторно бросить исключение, Вам не нужен блок попытки/выгоды. Обычно необходимо только поймать исключения, когда можно обработать их. Иначе позвольте им распространить вверх.