1

I hava a large log C# file. My client complained that some SessionIds are 00000000-0000-0000-0000-000000000000. First method

public static StartServiceLog CreateStartServiceLog(string serviceName, Guid sessionId = new Guid(), Device device = null, string userId = null)
{
    if (device == null)
    {
        device = CreateDeviceInfo();
    }

    return new StartServiceLog(device, DateTime.UtcNow, sessionId, userId, new List<string>() { serviceName });
}

I call this method

    var session = new StartSessionLog
    {
        Sid = sessionId,
        Device = device,
        Timestamp = DateTime.UtcNow,
    };
    return session;

How to find out when SessionIds are going to have all zeros or will be overwritten?

MikiBelavista
  • 2,470
  • 10
  • 48
  • 70

3 Answers3

6

System.Guid is a struct, not a class. This means that its parameterless constructor cannot do any work, and so, new Guid() == default.

The default value for structs is all members set to default values. In the case of Guid, it is a bunch of numbers, so its visual representation ends up all zeros.

To create a Guid with an actual value, you need to call the Guid.NewGuid() static method. This cannot be done within the default parameter initializer, so you would need to change your method to take the nullable Guid? instead:

public static void Foo(string etcetera, Guid? sessionId = null)
{
    if (sessionId == null)
    {
        sessionId = Guid.NewGuid();
    }

    // Do something with `sessionId.Value`
}
  • 1
    Oddly enough, even if the default constructor *does* do work (if you coded it in IL), it would not be executed in this case, this *really is* a case of `default(Guid)` it's just initialized to all 0's. You can see this in IL [on Sharplab](https://sharplab.io/#v2:C4LglgNgPgAgTARgLACgYGYAE9MGFMDeqmJ2WMALJgLIAUA4gK5gAmmA5s2wLyYsCmAMwCGjCMACUhYqQC+MkhmxVqcBlw4beAO34B3TE1a0JUoilKZ5KWUA) – Charlieface May 07 '21 at 13:55
  • @Charlieface I don't know much about IL, but is it even legal to define a default constructor for value types there? Either way, it makes sense that the C# compiler assumes C# rules for optional parameter initialization. – This company is turning evil. May 07 '21 at 14:20
  • 1
    Nothing to stop you in IL, but yeah, C# would not execute it. – Charlieface May 07 '21 at 14:26
5

I think you are mistakenly using new Guid() instead of Guid.NewGuid() to generate a brand new Guid.

Look at this example:

Console.WriteLine(new Guid());
Console.WriteLine(Guid.NewGuid());

Which outputs:

00000000-0000-0000-0000-000000000000
1b8640a1-a9d0-42c5-aaff-a87831687792

The problem is that Guid.NewGuid() cannot be used as a default value for a parameter because it is not a compile-time constant.

Instead you could do something like:

public static StartServiceLog CreateStartServiceLog(string serviceName, Guid? sessionId = null, Device device = null, string userId = null)
{
    if (sessionId == null)
        sessionId = Guid.NewGuid();
    ...

Set the default value of sessionId to be NULL and then if it is then create a new guid correctly in your method.

Martin
  • 16,093
  • 1
  • 29
  • 48
2

new Guid() doesn't generate a new Guid, it just returns all zeroes. Use Guid.NewGuid() instead (which of course can't be used as default value).

A simple pattern to use this in an optional argument would be something like this:

void DoSomething(Guid? id = default)
{
  id ??= Guid.NewGuid();
}
Luaan
  • 62,244
  • 7
  • 97
  • 116