2013-05-22 3 views
3

у меня есть этот код ...int.TryParse перепишет значение целого числа, переданное в качестве выходного параметра

var i = int.MinValue; 
var s = string.Empty; 
int.TryParse(s, out i); 

После того, как TryParse заявления, значение переменной i будет переписан (as zero) и моим предыдущее значение теряется.

Это ошибка? Если «Нет», есть ли какие-либо подробности реализации относительно необходимости повторной инициализации переменной, переданной в качестве параметра out.

+0

'default (int) == 0' –

+0

Вам не нужно инициализировать i, заменить первую строку на' int i; ', и код должен по-прежнему работать. –

ответ

8

В целом out является то, что он гарантирует (ну, на уровне C# хотя бы ... не уровень ИЛ), чтобы перезаписать это значение. Целью этого является избежать ненужных заданий, при этом разрешая «определенное задание».Например:

int i; // note: not assigned 
var s = string.Empty; 

// here "i" is not "definitely assigned" 
int.TryParse(s, out i); 
// here "i" is "definitely assigned" 

Идея заключается в том, что вы используете возвращаемое значение, например:

if(int.TryParse(s, out i)) { 
    // here "i" makes sense; feel free to use it 
} else { 
    // here you shouldn't use the value of "i" 
} 

В вашем конкретном случае, вы можете изменить порядок:

if(!int.TryParse(s, out i)) i = int.MinValue; 

В частности, , обратите внимание, что (в C#, по крайней мере) метод должен присвоить значение, а не может использовать входящее значение; например:

static void Foo(out int i) { 
    return; // error: hasn't assigned to i 
} 
static void Bar(out int i) { 
    int j = i; // error: cannot read from "i" until Bar has assigned a value 
    i = j; 
} 
static void Baz(out int i) { 
    i = 0; // note that after this assignment, code in Baz can read from "i" 
} 

Контраст к ref; при прохождении ref значения, требуется, чтобы быть определенно назначенным у вызывающего. Сам метод может или не может просмотреть входящее значение (как он выбирает), и может или не может присвоить новое значение (по его выбору). Например:

int i; 
SomeMethod(ref i); // illegal - "i" is not definitely assigned 

int i = 0; 
SomeMethod(ref i); // legal 

и:

static void Foo(ref int i) { 
    return; // perfectly legal to not look at "i" and/or not assign "i" 
} 
static void Foo(ref int i) { 
    i = i + 1; // perfectly legal to look at "i" and/or assign "i" 
} 
+1

Я собираюсь выбрать ваш ответ в качестве ответа из-за ясного объяснения вопроса и примеров с использованием вне. Пожалуйста, добавьте сравнение для 'ref' в свой ответ, потому что я думаю, что если переменная была передана как параметр' ref', чем ожидалось, она была инициализирована ... –

+0

@NaveedButt done –

5

Это не ошибка, но при возврате преобразования возвращается ноль. возвращаемое значение функции в этом случае будет ложным.

Когда этот метод возвращает, содержит 32-разрядное целое значение эквивалентно количеству содержащегося в сек, если преобразование удалось, или ноль, если преобразование не удалось. Преобразование завершается с ошибкой, если параметр s равен нулю, не соответствует формату или представляет номер меньше, чем MinValue или больше MaxValue. Этот параметр равен , передан неинициализированным. не

http://msdn.microsoft.com/en-us/library/f02979c7.aspx

0

Нет это не ошибка, если вы установите на значение переменных сек, например, «3»

var s = "3"; 

вы получите значение из я буду равен 3

, если вы установили string.Empty это будет нулевое значение по умолчанию.

Вы можете взглянуть на декомпилированный код реализации

internal static unsafe bool TryParseInt32(string s, NumberStyles style, NumberFormatInfo info, out int result) 
{ 
    byte* stackBuffer = stackalloc byte[114]; 
    Number.NumberBuffer number = new Number.NumberBuffer(stackBuffer); 
    result = 0; 
    if (!Number.TryStringToNumber(s, style, ref number, info, false)) 
    return false; 
    if ((style & NumberStyles.AllowHexSpecifier) != NumberStyles.None) 
    { 
    if (!Number.HexNumberToInt32(ref number, ref result)) 
     return false; 
    } 
    else if (!Number.NumberToInt32(ref number, ref result)) 
    return false; 
    return true; 
} 

результат: 0;

2

out (C# Reference)

Хотя переменные, передаваемые в качестве аргументов из не должны быть инициализированы до того, как пройдена, метод вызова требуется присвойте значение перед возвратом метода.

Int32.Parse инициализирует его default(int), который равен нулю.

Когда этот метод возвращает, содержит 32-разрядное целое значение, эквивалентное количеству содержащегося в s, если преобразование удалось, или ноль, если преобразование не удалось.

1

Это не ошибка, потому что это параметр out. В качестве упражнения попробуйте написать C#, который не устанавливает значение параметра out. (Подсказка: это невозможно) Поэтому результат, который вы наблюдаете, является единственным логическим - переменная out не «повторно инициализирована», она просто инициализирована.

Если TryParse был написан для принятия ref int, то то, что вы хотели, было бы возможно. Лично я думаю, что int здесь лучше.

Смежные вопросы