如果您查看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的值是未定义的.那么,为什么需要分配this给Guid.Empty?
这更像是一种风格而不是其他任何东西 - 在功能上它是多余的,编译器甚至可以Guid.Empty在生成的代码中优化分配.
防御性编码建议变量应始终具有明确分配的初始值.为什么?因为它减少了歧义,特别是对于那些不熟悉给定编程语言/平台细节的人.例如,人们可能会问:
说明:
Guid id = Guid.Empty;
Run Code Online (Sandbox Code Playgroud)
所有这些问题基本上都是通过阅读代码来解决的,而无需借助阅读文档和/或来源.此外,显式变量id开始是空的,这向读者表明它将在代码中稍后设置其值.
我猜这是一个历史文物.
在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() 方法。这里正在分配默认值。
| 归档时间: |
|
| 查看次数: |
1516 次 |
| 最近记录: |