Керівництво - це всі 0 (нулі)?


241

Я тестую деякі сервіси WCF, які надсилають об'єкти із Посібниками туди-сюди. У своєму тестовому коді веб-додатків я виконую наступні дії:

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

Чомусь виклик до нового Guid () генерує Guids із усіма 0 (нулями) на зразок цього:

00000000-0000-0000-0000-000000000000

Що може бути причиною цього?


9
Після редагування це абсолютно нове запитання. І для визначення нової відповіді потрібно набагато більше інформації.
Скотт Ріппі

3
Видалено відредаговану частину, яка змінила питання.
Дидаксис

115
+1, тому що я кілька разів використовував це питання, щоб вкрасти порожню настанову :)
jmosesman

5
@jmosesman, краще скористатись формоюGuid.Empty
Jonathan Moosekian

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
Чи компілюється вона в той самий ІЛ, 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. Це в основному те саме, що створити "новий" 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

1
g1буде компілюватися лише як поле, а не як локальна змінна. Також показники у колонці ваших коментарів не збігаються з тим самим рядком коду
CodesInChaos

1
@CodeInChaos: спасибі, виправили коментарі. FYI, рядок g1 насправді компілюється ...
JohnD

3
Він складеться так, як є, але не має визначеного значення. Якщо ви додасте код, який читає його (перш ніж писати до нього), він більше не буде компілюватися.
CodesInChaos

1
Правильно, добре, ви отримаєте помилку, якщо будете використовувати неініціалізовану змінну, тому значення не можна використовувати.
JohnD

1
поголосом, оскільки рядок "Guid = Guid.NewGuid ();" може заплутати нових розробників. Спробуйте відредагувати щось на зразок "Guid someGuid = Guid.NewGuid ();" як рядок g2;)
daviesdoesit



11

У дусі завершеності відповіді, які наказують вам використовувати, Guid.NewGuid()є правильними.

Звертаючись до наступного редагування, вам потрібно буде розмістити код для свого RequestObjectкласу. Я підозрюю, що ваша властивість guid не позначена як "a" DataMember, і тому не серіалізується по дроту. Оскільки default(Guid)це те саме, що new Guid()(тобто всі 0), це пояснило б поведінку, яку ви бачите.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.