为什么Guid构造函数的源代码包含"this = Guid.Empty"这一行?

neo*_*ium 13 .net c#

如果您查看Guid(string) .NET 4.5.2源代码中构造函数的源代码,则如下所示:

public Guid(String g)
{
    if (g==null) {
        throw new ArgumentNullException("g");
    }
    Contract.EndContractBlock();
    this = Guid.Empty;

    GuidResult result = new GuidResult();
    result.Init(GuidParseThrowStyle.All);
    if (TryParseGuid(g, GuidStyles.Any, ref result)) {
        this = result.parsedGuid;
    }
    else {
        throw result.GetGuidParseException();
    }
}
Run Code Online (Sandbox Code Playgroud)

问题是该生产线的目的是什么this = Guid.Empty;

从我可以看到,如果string g可以在TryParseGuid方法中成功解析,那么this将被分配.如果不能,那么将抛出异常.

假设你写道:

var guid = new Guid("invalidguid");
Run Code Online (Sandbox Code Playgroud)

这会导致异常,并且我会假设guid的值是未定义的.那么,为什么需要分配thisGuid.Empty

Ric*_*ner 7

这更像是一种风格而不是其他任何东西 - 在功能上它是多余的,编译器甚至可以Guid.Empty在生成的代码中优化分配.

防御性编码建议变量应始终具有明确分配的初始值.为什么?因为它减少了歧义,特别是对于那些不熟悉给定编程语言/平台细节的人.例如,人们可能会问:

  • Guid的默认值是多少?
  • 它应该是一个新的Guid吗?
  • 它应该全是零吗?
  • 它应该是其他一些不确定的国家吗?

说明:

Guid id = Guid.Empty;
Run Code Online (Sandbox Code Playgroud)

所有这些问题基本上都是通过阅读代码来解决的,而无需借助阅读文档和/或来源.此外,显式变量id开始是空的,这向读者表明它将在代码中稍后设置其值.


Dam*_*ver 5

这是一个历史文物.

在3.5版本中,GUID是就地构造的,所有文本解析都包含在构造函数方法本身中.

我猜想有一次开发人员决定将所有解析代码重构为辅助方法1,此时他们已经遇到编译器错误,因为this在调用实例方法之前必须明确分配.

GuidResult助手结构似乎在某个时间点等,此时这些分析方法可能再成为被引入static对和工作GuidResult,而不是实际Guid目前正在建设-在这一点,一切都变得简单又并明确分配不需要.


这是反射器将3.5版本反编译为:

public Guid(string g)
{
    if (g == null)
    {
        throw new ArgumentNullException("g");
    }
    int startIndex = 0;
    int parsePos = 0;
    try
    {
        int num2;
        long num3;
        if (g.IndexOf('-', 0) >= 0)
        {
            string str = g.Trim();
            if (str[0] == '{')
            {
                if ((str.Length != 0x26) || (str[0x25] != '}'))
                {
                    throw new FormatException(Environment.GetResourceString("Format_GuidInvLen"));
                }
                startIndex = 1;
            }
            else if (str[0] == '(')
            {
                if ((str.Length != 0x26) || (str[0x25] != ')'))
                {
                    throw new FormatException(Environment.GetResourceString("Format_GuidInvLen"));
                }
                startIndex = 1;
            }
            else if (str.Length != 0x24)
            {
                throw new FormatException(Environment.GetResourceString("Format_GuidInvLen"));
            }
            if (((str[8 + startIndex] != '-') || (str[13 + startIndex] != '-')) || ((str[0x12 + startIndex] != '-') || (str[0x17 + startIndex] != '-')))
            {
                throw new FormatException(Environment.GetResourceString("Format_GuidDashes"));
            }
            parsePos = startIndex;
            this._a = TryParse(str, ref parsePos, 8);
            parsePos++;
            this._b = (short) TryParse(str, ref parsePos, 4);
            parsePos++;
            this._c = (short) TryParse(str, ref parsePos, 4);
            parsePos++;
            num2 = TryParse(str, ref parsePos, 4);
            parsePos++;
            startIndex = parsePos;
            num3 = ParseNumbers.StringToLong(str, 0x10, 0x2000, ref parsePos);
            if ((parsePos - startIndex) != 12)
            {
                throw new FormatException(string.Format(CultureInfo.CurrentCulture, Environment.GetResourceString("Format_GuidInvLen"), new object[0]));
            }
            this._d = (byte) (num2 >> 8);
            this._e = (byte) num2;
            num2 = (int) (num3 >> 0x20);
            this._f = (byte) (num2 >> 8);
            this._g = (byte) num2;
            num2 = (int) num3;
            this._h = (byte) (num2 >> 0x18);
            this._i = (byte) (num2 >> 0x10);
            this._j = (byte) (num2 >> 8);
            this._k = (byte) num2;
        }
        else if (g.IndexOf('{', 0) >= 0)
        {
            int num5 = 0;
            int length = 0;
            g = EatAllWhitespace(g);
            if (g[0] != '{')
            {
                throw new FormatException(Environment.GetResourceString("Format_GuidBrace"));
            }
            if (!IsHexPrefix(g, 1))
            {
                throw new FormatException(string.Format(CultureInfo.CurrentCulture, Environment.GetResourceString("Format_GuidHexPrefix"), new object[] { "{0xdddddddd, etc}" }));
            }
            num5 = 3;
            length = g.IndexOf(',', num5) - num5;
            if (length <= 0)
            {
                throw new FormatException(Environment.GetResourceString("Format_GuidComma"));
            }
            this._a = ParseNumbers.StringToInt(g.Substring(num5, length), 0x10, 0x1000);
            if (!IsHexPrefix(g, (num5 + length) + 1))
            {
                throw new FormatException(string.Format(CultureInfo.CurrentCulture, Environment.GetResourceString("Format_GuidHexPrefix"), new object[] { "{0xdddddddd, 0xdddd, etc}" }));
            }
            num5 = (num5 + length) + 3;
            length = g.IndexOf(',', num5) - num5;
            if (length <= 0)
            {
                throw new FormatException(Environment.GetResourceString("Format_GuidComma"));
            }
            this._b = (short) ParseNumbers.StringToInt(g.Substring(num5, length), 0x10, 0x1000);
            if (!IsHexPrefix(g, (num5 + length) + 1))
            {
                throw new FormatException(string.Format(CultureInfo.CurrentCulture, Environment.GetResourceString("Format_GuidHexPrefix"), new object[] { "{0xdddddddd, 0xdddd, 0xdddd, etc}" }));
            }
            num5 = (num5 + length) + 3;
            length = g.IndexOf(',', num5) - num5;
            if (length <= 0)
            {
                throw new FormatException(Environment.GetResourceString("Format_GuidComma"));
            }
            this._c = (short) ParseNumbers.StringToInt(g.Substring(num5, length), 0x10, 0x1000);
            if ((g.Length <= ((num5 + length) + 1)) || (g[(num5 + length) + 1] != '{'))
            {
                throw new FormatException(Environment.GetResourceString("Format_GuidBrace"));
            }
            length++;
            byte[] buffer = new byte[8];
            for (int i = 0; i < 8; i++)
            {
                if (!IsHexPrefix(g, (num5 + length) + 1))
                {
                    throw new FormatException(string.Format(CultureInfo.CurrentCulture, Environment.GetResourceString("Format_GuidHexPrefix"), new object[] { "{... { ... 0xdd, ...}}" }));
                }
                num5 = (num5 + length) + 3;
                if (i < 7)
                {
                    length = g.IndexOf(',', num5) - num5;
                    if (length <= 0)
                    {
                        throw new FormatException(Environment.GetResourceString("Format_GuidComma"));
                    }
                }
                else
                {
                    length = g.IndexOf('}', num5) - num5;
                    if (length <= 0)
                    {
                        throw new FormatException(Environment.GetResourceString("Format_GuidBraceAfterLastNumber"));
                    }
                }
                uint num8 = (uint) Convert.ToInt32(g.Substring(num5, length), 0x10);
                if (num8 > 0xff)
                {
                    throw new FormatException(Environment.GetResourceString("Overflow_Byte"));
                }
                buffer[i] = (byte) num8;
            }
            this._d = buffer[0];
            this._e = buffer[1];
            this._f = buffer[2];
            this._g = buffer[3];
            this._h = buffer[4];
            this._i = buffer[5];
            this._j = buffer[6];
            this._k = buffer[7];
            if ((((num5 + length) + 1) >= g.Length) || (g[(num5 + length) + 1] != '}'))
            {
                throw new FormatException(Environment.GetResourceString("Format_GuidEndBrace"));
            }
            if (((num5 + length) + 1) != (g.Length - 1))
            {
                throw new FormatException(Environment.GetResourceString("Format_ExtraJunkAtEnd"));
            }
        }
        else
        {
            string s = g.Trim();
            if (s.Length != 0x20)
            {
                throw new FormatException(Environment.GetResourceString("Format_GuidInvLen"));
            }
            for (int j = 0; j < s.Length; j++)
            {
                char c = s[j];
                if ((c < '0') || (c > '9'))
                {
                    char ch2 = char.ToUpper(c, CultureInfo.InvariantCulture);
                    if ((ch2 < 'A') || (ch2 > 'F'))
                    {
                        throw new FormatException(Environment.GetResourceString("Format_GuidInvalidChar"));
                    }
                }
            }
            this._a = ParseNumbers.StringToInt(s.Substring(startIndex, 8), 0x10, 0x1000);
            startIndex += 8;
            this._b = (short) ParseNumbers.StringToInt(s.Substring(startIndex, 4), 0x10, 0x1000);
            startIndex += 4;
            this._c = (short) ParseNumbers.StringToInt(s.Substring(startIndex, 4), 0x10, 0x1000);
            startIndex += 4;
            num2 = (short) ParseNumbers.StringToInt(s.Substring(startIndex, 4), 0x10, 0x1000);
            startIndex += 4;
            parsePos = startIndex;
            num3 = ParseNumbers.StringToLong(s, 0x10, startIndex, ref parsePos);
            if ((parsePos - startIndex) != 12)
            {
                throw new FormatException(string.Format(CultureInfo.CurrentCulture, Environment.GetResourceString("Format_GuidInvLen"), new object[0]));
            }
            this._d = (byte) (num2 >> 8);
            this._e = (byte) num2;
            num2 = (int) (num3 >> 0x20);
            this._f = (byte) (num2 >> 8);
            this._g = (byte) num2;
            num2 = (int) num3;
            this._h = (byte) (num2 >> 0x18);
            this._i = (byte) (num2 >> 0x10);
            this._j = (byte) (num2 >> 8);
            this._k = (byte) num2;
        }
    }
    catch (IndexOutOfRangeException)
    {
        throw new FormatException(Environment.GetResourceString("Format_GuidUnrecognized"));
    }
}
Run Code Online (Sandbox Code Playgroud)

显然在3.5和4.5.2之间,已经引入了辅助方法.从那里开始,假设首先引入辅助方法(作为实例方法,因此需要明确赋值),然后GuidResult引入辅助结构().

如果您将所有4.5.2代码复制到一个新项目中,删除您询问和编译的行,一切都很好.


1可能支持引入似乎已出现在.NET 4.0时间范围内的Parse/ TryParsemethods Guid.


小智 -1

Guid.Empty 将分配全零。如果您不想分配全零,您可以使用 Guid.NewGuid() 方法。这里正在分配默认值。

  • 不确定这如何回答问题,因为 `this=Guild.Empty` 在技术上是毫无意义的 - 结构的默认值甚至在分配之前就已经是“全零”。 (2认同)