Guid это все 0 (нули)?

241

Я тестирую некоторые сервисы WCF, которые отправляют объекты с Guids туда и обратно. В тестовом коде моего веб-приложения я делаю следующее:

var responseObject = proxy.CallService(new RequestObject
{
    Data = "misc. data",
    Guid = new Guid()
});

По какой-то причине вызов new Guid () генерирует Guids со всеми 0 (нулями) следующим образом:

00000000-0000-0000-0000-000000000000

Что может быть причиной этого?

Didaxis
источник
9
После редактирования это совершенно новый вопрос. И намного больше информации необходимо, чтобы определить новый ответ.
Скотт Риппи
3
Удалена отредактированная часть, которая изменила вопрос.
Дидаксис
116
+1, потому что я использовал этот вопрос, чтобы украсть пустой гид десятки раз :)
jmosesman
5
@jmosesman, лучше использовать формуGuid.Empty
Джонатан Мускиан
4
@JonathanM Я на самом деле использую его в сценарии SQL. Этот пост появляется первым после поиска.
jmosesman

Ответы:

428

Используйте статический метод Guid.NewGuid()вместо вызова конструктора по умолчанию.

var responseObject = proxy.CallService(new RequestObject
{
    Data = "misc. data",
    Guid = Guid.NewGuid()
});
Марк Байерс
источник
18
+1 за правильный ответ, а также ссылку на соответствующую документацию.
ObscureRobot
109

Уроки, которые можно извлечь из этого:

1) Guid - это тип значения, а не ссылочный тип.

2) Вызов конструктора new S()по умолчанию для любого типа значения всегда возвращает вам нулевую форму этого типа значения, какой бы она ни была. Это логически так же, как default(S).

Эрик Липперт
источник
3
Компилируется ли он в тот же IL, default(S)или есть какие-то тонкости, которые мне не хватает?
Конфигуратор
8
@configurator: так и есть. Фактически, внутреннее представление компилятора «default (S)» и «new S ()» одинаково; мы не различаем их внутренне, что привело к некоторым неудачным ошибкам за эти годы, потому что они на самом деле не совсем идентичны. Например, const int x = new int();не должно быть законным в соответствии со спецификацией, но const int x = default(int);есть; мы разрешаем оба.
Эрик Липперт
1
@configurator - если вас интересуют связанные с этим случаи, возможно, будет интересен msmvps.com/blogs/jon_skeet/archive/2008/12/10/… .
KVB
56

Попробуйте это вместо этого:

var responseObject = proxy.CallService(new RequestObject
{
    Data = "misc. data",
    Guid = new Guid.NewGuid()
});

Это сгенерирует «реальное» значение Guid. Когда вы создаете ссылочный тип, он даст вам значение по умолчанию (в данном случае это все нули для Guid).

Когда вы создаете новый Guid, он инициализирует его всеми нулями, что является значением по умолчанию для Guid. По сути, это то же самое, что и создание «нового» int (тип значения, но вы можете сделать это в любом случае):

Guid g1;                    // g1 is 00000000-0000-0000-0000-000000000000
Guid g2 = new Guid();       // g2 is 00000000-0000-0000-0000-000000000000
Guid g3 = default(Guid);    // g3 is 00000000-0000-0000-0000-000000000000
Guid g4 = Guid.NewGuid();   // g4 is not all zeroes

Сравните это с тем же, что и с int:

int i1;                     // i1 is 0
int i2 = new int();         // i2 is 0
int i3 = default(int);      // i3 is 0
JohnD
источник
1
g1будет компилироваться только как поле, а не как локальная переменная. Также индексы в вашем столбце комментариев не совпадают с той же строкой кода
CodesInChaos
1
@CodeInChaos: Спасибо, исправил комментарии. К вашему сведению, строка g1 действительно компилируется ...
JohnD
3
Он будет скомпилирован как есть, но не имеет определенного значения. Если вы добавите код, который читает его (до записи в него), он больше не будет компилироваться.
CodesInChaos
1
Хорошо, хорошо, вы получите ошибку, если вы используете неинициализированную переменную, поэтому значение не может быть использовано.
JohnD
1
проголосовали против, потому что строка "Guid = Guid.NewGuid ();" может сбить с толку новых разработчиков. Попробуйте редактировать что-то вроде "Guid someGuid = Guid.NewGuid ();" как линия g2;)
daviesdoesit
25

Попробуйте сделать:

Guid foo = Guid.NewGuid();
Дилан Смит
источник
1
Причина понижения: «Guid» является типом, но используется как переменная.
Дэвисдоэсит
19

Не могу сказать, сколько раз это поймали. меня.

Guid myGuid = Guid.NewGuid(); 
Мэтт Доуди
источник
11

В духе полноты ответы, которые инструктируют вас использовать Guid.NewGuid(), верны.

При рассмотрении вашего последующего редактирования вам нужно будет опубликовать код для вашего RequestObjectкласса. Я подозреваю, что ваше свойство guid не помечено как DataMemberи, следовательно, не сериализуется по проводам. Поскольку default(Guid)это то же самое, что new Guid()(то есть все 0), это объясняет поведение, которое вы видите.

Адам Робинсон
источник