Который является лучшим, возвращаемым значением или параметром?

В Java исходный код сначала компилируется в байт-код, а затем выполняется интерпретатором (JVM - виртуальная машина Java).

Байт-код представляет собой машинный код для виртуальной машины.

В Javascript есть среда выполнения (движок), которая выполняет только временную компиляцию (JIT). По сути, во время выполнения ему дается исходный код, который он немедленно преобразует в собственный код, а затем код выполняется. В движке Chrome есть два модуля, которые выполняют компиляцию: один может выполнять код быстро, но код не сильно оптимизирован (интерпретатор зажигания), а другой создает высокопроизводительный код, но компиляция занимает больше времени (турбореактивный компилятор).

Зачем использовать оба:

  • переносимость - когда вы используете промежуточное представление, скомпилированное AOT, вы можете взять этот байт-код и запустить его на любой архитектуре, для которой предоставляется виртуальная машина. Вы можете передать один и тот же байт-код Java клиентам на Mac, ПК или Linux. Если у них установлена ​​JVM, код будет запущен. Для C или C ++ вы должны поставлять разные исполняемые программы для каждой архитектуры
  • быстрый начальный запуск и достойная производительность выполнения - компиляция требует времени (и чем больше оптимизированного кода, тем больше времени требуется для компиляции в целом), но никто не любит Подождите. Лучше создать что-то неидеальное (фаза зажигания), а затем постепенно улучшать код путем компиляции горячих путей в высокооптимизированный машинный код (фаза турбовентилятора). Это особенно вероятно сегодня, когда у нас есть процессоры со многими ядрами, но мы не можем использовать их все, потому что создавать программы с множеством параллельных потоков сложно (поэтому одно ядро ​​может выполнять программу, а другое может оптимизировать код в это время)
  • [ 119]
139
задан Vimvq1987 1 May 2009 в 09:37
поделиться

11 ответов

Возвращаемые значения почти всегда правильный выбор, когда метод не имеет ничего другого для возврата. (На самом деле, я не могу вспомнить ни одного случая, когда бы когда-либо хотел бы использовать метод void с параметром out , если бы у меня был выбор. Деконструкция C # 7 методы для поддерживаемой языком деконструкции действуют как очень, очень редкое исключение из этого правила.)

Помимо всего прочего, это мешает вызывающей стороне объявлять переменную отдельно:

int foo;
GetValue(out foo);

vs

int foo = GetValue();

Out значения также предотвращают создание цепочек методов следующим образом:

Console.WriteLine(GetValue().ToString("g"));

(Действительно, это также одна из проблем с установщиками свойств, и поэтому шаблон построителя использует методы, которые возвращают построитель, например, myStringBuilder.Append (xxx) .Append. (YYY) ).

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

Возвращаемые значения FTW.

РЕДАКТИРОВАТЬ: С точки зрения того, что происходит ...

В основном, когда вы передаете аргумент для параметра "out", вы должны передать переменную. (Элементы массива также классифицируются как переменные.) В методе, который вы вызываете, нет «новой» переменной в стеке для параметра - он использует вашу переменную для хранения. Любые изменения в переменной сразу видны. Вот пример, показывающий разницу:

using System;

class Test
{
    static int value;

    static void ShowValue(string description)
    {
        Console.WriteLine(description + value);
    }

    static void Main()
    {
        Console.WriteLine("Return value test...");
        value = 5;
        value = ReturnValue();
        ShowValue("Value after ReturnValue(): ");

        value = 5;
        Console.WriteLine("Out parameter test...");
        OutParameter(out value);
        ShowValue("Value after OutParameter(): ");
    }

    static int ReturnValue()
    {
        ShowValue("ReturnValue (pre): ");
        int tmp = 10;
        ShowValue("ReturnValue (post): ");
        return tmp;
    }

    static void OutParameter(out int tmp)
    {
        ShowValue("OutParameter (pre): ");
        tmp = 10;
        ShowValue("OutParameter (post): ");
    }
}

Результаты:

Return value test...
ReturnValue (pre): 5
ReturnValue (post): 5
Value after ReturnValue(): 10
Out parameter test...
OutParameter (pre): 5
OutParameter (post): 10
Value after OutParameter(): 10

Разница на этапе «после» - т.е. после того, как локальная переменная или параметр были изменены. В тесте ReturnValue это не имеет значения для статической переменной value . В тесте OutParameter переменная value изменяется строкой tmp = 10;

150
ответ дан 23 November 2019 в 23:21
поделиться

I think one of the few scenarios where it would be useful would be when working with unmanaged memory, and you want to make it obvious that the "returned" value should be disposed of manually, rather than expecting it to be disposed of on its own.

1
ответ дан 23 November 2019 в 23:21
поделиться

Реальной разницы нет, выходные параметры в C # позволяют методу возвращать более одного значения, вот и все.

Однако есть некоторые небольшие различия, но ни одна из них не очень важна :

Использование параметра out заставит вас использовать две строки, такие как:

int n;
GetValue(n);

, а использование возвращаемого значения позволит вам сделать это в одной строке:

int n = GetValue();

Другое отличие (корректно только для типов значений и только если C # не делает встроенная функция) заключается в том, что использование возвращаемого значения обязательно сделает копию значения, когда функция, возвращаемая при использовании параметра OUT, не обязательно сделает это.

1
ответ дан 23 November 2019 в 23:21
поделиться

I would prefer the following instead of either of those in this simple example.

public int Value
{
    get;
    private set;
}

But, they are all very much the same. Usually, one would only use 'out' if they need to pass multiple values back from the method. If you want to send a value in and out of the method, one would choose 'ref'. My method is best, if you are only returning a value, but if you want to pass a parameter and get a value back one would likely choose your first choice.

2
ответ дан 23 November 2019 в 23:21
поделиться

Вы почти всегда должны использовать возвращаемое значение. Параметры « out » создают небольшие трения для большого количества API, композиционности и т. Д.

Наиболее примечательное исключение, которое приходит на ум, - это когда вы хотите вернуть несколько значений (.Net Framework не ' не может иметь кортежи до 4.0), например, с шаблоном TryParse .

5
ответ дан 23 November 2019 в 23:21
поделиться

You should generally prefer a return value over an out param. Out params are a neccissary evil if you find yourself writing code that needs to do 2 things. A good example of this is the Try pattern (such as Int32.TryParse).

Let's consider what the caller of your two methods would have to do. For the first example I can write this...

int foo = GetValue();

Notice that I can declare a variable and assign it via your method in one line. FOr the 2nd example it looks like this...

int foo;
GetValue(out foo);

I'm now forced to declare my variable up front and write my code over two lines.

update

A good place to look when asking these types of question is the .NET Framework Design Guidelines. If you have the book version then you can see the annotations by Anders Hejlsberg and others on this subject (page 184-185) but the online version is here...

http://msdn.microsoft.com/en-us/library/ms182131(VS.80).aspx

If you find yourself needing to return two things from an API then wrapping them up in a struct/class would be better than an out param.

23
ответ дан 23 November 2019 в 23:21
поделиться

Это предпочтение в основном

Я предпочитаю возвраты, и если у вас есть несколько возвращений, вы можете заключить их в Resto DTO

public class Result{
  public Person Person {get;set;}
  public int Sum {get;set;}
}
8
ответ дан 23 November 2019 в 23:21
поделиться

Вы можете иметь только одно возвращаемое значение, в то время как вы можете иметь несколько выходных параметров.

В этих случаях вам нужно учитывать только параметры вывода.

Однако, если вам нужно чтобы вернуть более одного параметра из вашего метода, вы, вероятно, захотите посмотреть, что вы возвращаете из ОО-подхода, и подумать, лучше ли вам возвращать объект или структуру с этими параметрами. Поэтому вы снова возвращаетесь к возвращаемому значению.

5
ответ дан 23 November 2019 в 23:21
поделиться

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

public int ReturnMultiple(int input, out int output1, out int output2)
{
    output1 = input + 1;
    output2 = input + 2;

    return input;
}

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

РЕДАКТИРОВАТЬ: Одна из причин, по которой существует из , заключается в том, чтобы облегчить возврат нескольких значений из одного вызова метода:

public int ReturnMultiple(int input, out int output1, out int output2)
{
    output1 = input + 1;
    output2 = input + 2;

    return input;
}

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

РЕДАКТИРОВАТЬ: Одна из причин, по которой существует из , заключается в том, чтобы облегчить возврат нескольких значений из одного вызова метода:

public int ReturnMultiple(int input, out int output1, out int output2)
{
    output1 = input + 1;
    output2 = input + 2;

    return input;
}

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

РЕДАКТИРОВАТЬ: Это пример, демонстрирующий одну из причин существования ключевого слова. Вышеизложенное ни в коем случае нельзя считать наилучшей практикой.

26
ответ дан 23 November 2019 в 23:21
поделиться

Оба они имеют различное назначение и не рассматриваются то же самое компилятором. Если ваш метод должен вернуть значение, вы должны использовать return. Out используется там, где ваш метод должен возвращать несколько значений.

Если вы используете return, то данные сначала записываются в стек методов, а затем в вызывающий метод. Хотя в случае out он напрямую записывается в стек вызывающих методов. Не уверен, есть ли еще различия.

1
ответ дан 23 November 2019 в 23:21
поделиться

As others have said: return value, not out param.

May I recommend to you the book "Framework Design Guidelines" (2nd ed)? Pages 184-185 cover the reasons for avoiding out params. The whole book will steer you in the right direction on all sorts of .NET coding issues.

Allied with Framework Design Guidelines is the use of the static analysis tool, FxCop. You'll find this on Microsoft's sites as a free download. Run this on your compiled code and see what it says. If it complains about hundreds and hundreds of things... don't panic! Look calmly and carefully at what it says about each and every case. Don't rush to fix things ASAP. Learn from what it is telling you. You will be put on the road to mastery.

1
ответ дан 23 November 2019 в 23:21
поделиться
Другие вопросы по тегам:

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