I have an XML that contains several flags, some of them are unsigned 32-bit integers and others are unsigned 64-bit integers. Some of them are written in a comma-separated list and others are in hex style.
我有一个包含几个标志的XML,其中一些是无符号的32位整数,另一些是无符号的64位整数。其中一些是用逗号分隔的列表编写的,另一些是十六进制的。
See this example:
看这个例子:
<Color>Blue,Red</Color>
<Color>0xC</Color>
As I don't want to write a method to parse each enum, I decided to use a generic method. But Visual Studio won't let me build the solution. Here's my method:
因为我不想编写解析每个枚举的方法,所以我决定使用泛型方法。但Visual Studio不会让我构建解决方案。这是我的方法:
public static T ParseFlags<T>(string value) where T : struct
{
T result = (T)((object)0);
string[] array;
// Remove white spaces and delimit string if it is comma-separated
if (ParseDelimitedString(value, ',', out array))
{
for (int i = 0; i < array.Length; i++)
{
T flag = (T)((object)0);
// Check if value is member of enumeration
if (Enum.TryParse<T>(array[i], out flag))
{
result |= (T)((object)flag);
}
}
}
else
{
switch (Type.GetTypeCode(Enum.GetUnderlyingType(typeof(T))))
{
// Remove hex characters and parse node's inner text
case TypeCode.UInt32:
result = (T)((object)ParseUint(value));
break;
case TypeCode.UInt64:
result = (T)((object)ParseUlong(value));
break;
}
}
return result;
}
The error message I get is:
我得到的错误信息是:
Error 1 Operator '|=' cannot be applied to operands of type 'T' and 'T'
错误1运算符'| ='不能应用于'T'和'T'类型的操作数
Is there a way to do this?
有没有办法做到这一点?
4 个解决方案
#1
6
You are doing a lot of work that can be done for you. For example, if your enum
is declared with the FlagsAttribute
then Enum.Parse
will parse comma separated values for you.
你正在做很多可以为你做的工作。例如,如果使用FlagsAttribute声明枚举,则Enum.Parse将为您解析逗号分隔值。
public static T ParseFlags<T>(string value) where T : struct
{
T result;
ulong temp;
if (Enum.TryParse(value, out result))
{
return result;
}
string hexNum = value.StartsWith("0x") ? value.Substring(2) : value;
if (ulong.TryParse(hexNum, NumberStyles.HexNumber, null, out temp))
{
return (T)Enum.ToObject(typeof(T), temp);
}
throw new ArgumentException("value could not be parsed");
}
I tested this with various Flags enum types with short
, int
, and ulong
backing values.
我使用具有short,int和ulong支持值的各种Flags枚举类型对此进行了测试。
#2
1
If you know what type of enum you're parsing:
如果你知道你正在解析什么类型的枚举:
[Fact]
public void when_parsing_options_then_can_combine_flags()
{
var values = "Singleline | Compiled";
var options = values.Split(new[] { '|' }, StringSplitOptions.RemoveEmptyEntries)
.Select(value => (RegexOptions)Enum.Parse(typeof(RegexOptions), value))
.Aggregate(RegexOptions.None, (current, value) => current |= value);
Assert.Equal(RegexOptions.Singleline | RegexOptions.Compiled, options);
}
#3
0
Try this:
尝试这个:
public static T ParseFlags<T>(string value) where T : struct
{
long result = 0L;
string[] array;
// Remove white spaces and delimit string if it is comma-separated
if (ParseDelimitedString(value, ',', out array))
{
for (int i = 0; i < array.Length; i++)
{
T flag = default(T);
// Check if value is member of enumeration
if (Enum.TryParse<T>(array[i], out flag))
{
result |= (long)flag;
}
}
}
else
{
switch (Type.GetTypeCode(Enum.GetUnderlyingType(typeof(T))))
{
// Remove hex characters and parse node's inner text
case TypeCode.UInt32:
result = ParseUint(value);
break;
case TypeCode.UInt64:
result = ParseUlong(value);
break;
}
}
return (T)((object)result);
}
Hope it helps.
希望能帮助到你。
#4
0
"|=" usage in that snippet makes me think you meant to use the Enum as bitset not just any old Enum. If this is true, you should make a small change - declare the local "result" as int and adjust the casts appropriately, your return statement should then be "return (T)(object)result;". That line in question with "|" would look like: "result |= (int)(object)flag;". Perhaps, there is a better answer but, note that enums are integers and your scenario of bitset are covered well enough with this solution unless there are situations I missed or you did not state.
“| =”该片段中的用法让我觉得你的意思是将Enum用作bitset而不仅仅是任何旧的Enum。如果这是真的,你应该做一个小改动 - 将本地“result”声明为int并适当地调整强制转换,你的return语句应该是“return(T)(object)result;”。与“|”相关的那一行看起来像:“result | =(int)(object)flag;”。也许,有一个更好的答案,但是,请注意,枚举是整数,并且您的bitset情景已经足够好用这个解决方案,除非有我错过的情况或你没有陈述。
#1
6
You are doing a lot of work that can be done for you. For example, if your enum
is declared with the FlagsAttribute
then Enum.Parse
will parse comma separated values for you.
你正在做很多可以为你做的工作。例如,如果使用FlagsAttribute声明枚举,则Enum.Parse将为您解析逗号分隔值。
public static T ParseFlags<T>(string value) where T : struct
{
T result;
ulong temp;
if (Enum.TryParse(value, out result))
{
return result;
}
string hexNum = value.StartsWith("0x") ? value.Substring(2) : value;
if (ulong.TryParse(hexNum, NumberStyles.HexNumber, null, out temp))
{
return (T)Enum.ToObject(typeof(T), temp);
}
throw new ArgumentException("value could not be parsed");
}
I tested this with various Flags enum types with short
, int
, and ulong
backing values.
我使用具有short,int和ulong支持值的各种Flags枚举类型对此进行了测试。
#2
1
If you know what type of enum you're parsing:
如果你知道你正在解析什么类型的枚举:
[Fact]
public void when_parsing_options_then_can_combine_flags()
{
var values = "Singleline | Compiled";
var options = values.Split(new[] { '|' }, StringSplitOptions.RemoveEmptyEntries)
.Select(value => (RegexOptions)Enum.Parse(typeof(RegexOptions), value))
.Aggregate(RegexOptions.None, (current, value) => current |= value);
Assert.Equal(RegexOptions.Singleline | RegexOptions.Compiled, options);
}
#3
0
Try this:
尝试这个:
public static T ParseFlags<T>(string value) where T : struct
{
long result = 0L;
string[] array;
// Remove white spaces and delimit string if it is comma-separated
if (ParseDelimitedString(value, ',', out array))
{
for (int i = 0; i < array.Length; i++)
{
T flag = default(T);
// Check if value is member of enumeration
if (Enum.TryParse<T>(array[i], out flag))
{
result |= (long)flag;
}
}
}
else
{
switch (Type.GetTypeCode(Enum.GetUnderlyingType(typeof(T))))
{
// Remove hex characters and parse node's inner text
case TypeCode.UInt32:
result = ParseUint(value);
break;
case TypeCode.UInt64:
result = ParseUlong(value);
break;
}
}
return (T)((object)result);
}
Hope it helps.
希望能帮助到你。
#4
0
"|=" usage in that snippet makes me think you meant to use the Enum as bitset not just any old Enum. If this is true, you should make a small change - declare the local "result" as int and adjust the casts appropriately, your return statement should then be "return (T)(object)result;". That line in question with "|" would look like: "result |= (int)(object)flag;". Perhaps, there is a better answer but, note that enums are integers and your scenario of bitset are covered well enough with this solution unless there are situations I missed or you did not state.
“| =”该片段中的用法让我觉得你的意思是将Enum用作bitset而不仅仅是任何旧的Enum。如果这是真的,你应该做一个小改动 - 将本地“result”声明为int并适当地调整强制转换,你的return语句应该是“return(T)(object)result;”。与“|”相关的那一行看起来像:“result | =(int)(object)flag;”。也许,有一个更好的答案,但是,请注意,枚举是整数,并且您的bitset情景已经足够好用这个解决方案,除非有我错过的情况或你没有陈述。