C# 中的假枚举

发布于 2024-08-12 20:23:59 字数 2359 浏览 3 评论 0原文

我正在尝试使用本文中的代码:创建假枚举,但我不明白为什么它不起作用。

此代码:

Console.WriteLine(FakeEnum.One.FriendlyName);
Console.WriteLine(FakeEnum.Four.FriendlyName);

生成异常:

System.TypeInitializationException was unhandled
  Message="The type initializer for 'FakeEnum' threw an exception."
  Source="FakeEnum1"
  TypeName="FakeEnum"
  StackTrace:
       at FakeEnum1.Program.Main(String[] args) in ..\Test\FakeEnum1\Program.cs:line 26
       at System.AppDomain._nExecuteAssembly(Assembly assembly, String[] args)
       at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
       at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
       at System.Threading.ThreadHelper.ThreadStart()
  InnerException: System.NullReferenceException
       Message="Object reference not set to an instance of an object."
       Source="FakeEnum1"
       StackTrace:
            at FakeEnum.op_Equality(FakeEnum a, FakeEnum b) in ..\Test\FakeEnum1\FakeEnum.cs:line 158
            at FakeEnum.ToString(String format) in ..\Test\FakeEnum1\FakeEnum.cs:line 31
            at FakeEnum.ToString() in ..\Test\FakeEnum1\FakeEnum.cs:line 25
            at FakeEnum..ctor(Int32 value, String friendlyName) in ..\Test\FakeEnum1\FakeEnum.cs:line 171
            at FakeEnum..ctor(Int32 value) in ..\Test\FakeEnum1\FakeEnum.cs:line 165
            at FakeEnum..cctor() in ..\Test\FakeEnum1\FakeEnum.cs:line 13

如果我注释使用 (int) 构造函数声明的成员,则其他一切都有效:

public static readonly FakeEnum One = new FakeEnum(1, "One's Friendly Name");
public static readonly FakeEnum Two = new FakeEnum(2, "Two's Friendly Name");
public static readonly FakeEnum Three = new FakeEnum(3, "Three's Friendly Name");
//public static readonly FakeEnum Four = new FakeEnum(4);
//public static readonly FakeEnum Five = new FakeEnum(5);
//public static readonly FakeEnum Six = new FakeEnum(6);

现在,如果我将构造函数设置为 public,则以下代码工作得很好:

FakeEnum a = new FakeEnum(14, "1 4");
FakeEnum b = new FakeEnum(28);
Console.WriteLine(a.FriendlyName);
Console.WriteLine(b.FriendlyName);

我只是没有想法了 - 我错过了什么,以及在使用原始代码时产生异常的原因是什么?

I'm trying to use the code from this article: Creating Fake Enums, but I can't figure out why it doesn't work.

This code:

Console.WriteLine(FakeEnum.One.FriendlyName);
Console.WriteLine(FakeEnum.Four.FriendlyName);

generates an exception:

System.TypeInitializationException was unhandled
  Message="The type initializer for 'FakeEnum' threw an exception."
  Source="FakeEnum1"
  TypeName="FakeEnum"
  StackTrace:
       at FakeEnum1.Program.Main(String[] args) in ..\Test\FakeEnum1\Program.cs:line 26
       at System.AppDomain._nExecuteAssembly(Assembly assembly, String[] args)
       at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
       at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
       at System.Threading.ThreadHelper.ThreadStart()
  InnerException: System.NullReferenceException
       Message="Object reference not set to an instance of an object."
       Source="FakeEnum1"
       StackTrace:
            at FakeEnum.op_Equality(FakeEnum a, FakeEnum b) in ..\Test\FakeEnum1\FakeEnum.cs:line 158
            at FakeEnum.ToString(String format) in ..\Test\FakeEnum1\FakeEnum.cs:line 31
            at FakeEnum.ToString() in ..\Test\FakeEnum1\FakeEnum.cs:line 25
            at FakeEnum..ctor(Int32 value, String friendlyName) in ..\Test\FakeEnum1\FakeEnum.cs:line 171
            at FakeEnum..ctor(Int32 value) in ..\Test\FakeEnum1\FakeEnum.cs:line 165
            at FakeEnum..cctor() in ..\Test\FakeEnum1\FakeEnum.cs:line 13

If I comment the members declared with the (int) constructor, everything else works:

public static readonly FakeEnum One = new FakeEnum(1, "One's Friendly Name");
public static readonly FakeEnum Two = new FakeEnum(2, "Two's Friendly Name");
public static readonly FakeEnum Three = new FakeEnum(3, "Three's Friendly Name");
//public static readonly FakeEnum Four = new FakeEnum(4);
//public static readonly FakeEnum Five = new FakeEnum(5);
//public static readonly FakeEnum Six = new FakeEnum(6);

Now, if I make the constructors public, the following code works just fine:

FakeEnum a = new FakeEnum(14, "1 4");
FakeEnum b = new FakeEnum(28);
Console.WriteLine(a.FriendlyName);
Console.WriteLine(b.FriendlyName);

I just run out of ideas - what am I missing, and what generates the exception when using the original code?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

骄傲 2024-08-19 20:23:59

就是这样:

FakeEnum temp = staticField.GetValue(null) as FakeEnum;
if(temp == null) continue;

“==”正在调用 == 运算符,它不希望左侧为空:

public static bool operator == (FakeEnum a, FakeEnum b) { 
    return a.Equals(b);
}

您可以像这样修复运算符:(

public static bool operator == (FakeEnum a, FakeEnum b) { 
    if (object.ReferenceEquals(a, b)) {
        return true;
    }
    if (object.ReferenceEquals(a, null) || object.ReferenceEquals(b, null)) {
        return false;
    }
    return a.Equals(b);
}

或者使用 object.Equals,正如另一个答案中所指出的 - 哦!)

或者您可以更改它以使 Equals 委托给 == 而不是相反。

我个人认为这门课看起来有点毛茸茸的。我什至不清楚为什么 == 和 != 需要重载,或者为什么 Equals 需要重写,除非你确实有两个具有相同值的单独对象(例如,由于序列化,这将是令人讨厌的)反正)。

It's this bit:

FakeEnum temp = staticField.GetValue(null) as FakeEnum;
if(temp == null) continue;

That "==" is calling the == operator, which doesn't expect the left hand side to be null:

public static bool operator == (FakeEnum a, FakeEnum b) { 
    return a.Equals(b);
}

You can fix the operator like this:

public static bool operator == (FakeEnum a, FakeEnum b) { 
    if (object.ReferenceEquals(a, b)) {
        return true;
    }
    if (object.ReferenceEquals(a, null) || object.ReferenceEquals(b, null)) {
        return false;
    }
    return a.Equals(b);
}

(Or by using object.Equals, as pointed out in another answer - doh!)

or you could change it to make Equals delegate to == instead of the other way round.

Personally I'd say this class is looking a tad hairy. It's not even clear to me why == and != need overloading or indeed why Equals needs overriding unless you really have two separate objects with the same value (e.g. due to serialization, which is going to be icky anyway).

留蓝 2024-08-19 20:23:59

我自己还没有真正尝试过,但是 == 和 != 操作肯定没有正确实现。应该是:

public static bool operator == (FakeEnum a, FakeEnum b) { 
    return object.Equals(a,b);
}
public static bool operator != (FakeEnum a, FakeEnum b) { 
    return !object.Equals(a,b);
}

I haven't really tried it myself, but the == and != operations are definitely not implemented correctly. Should be:

public static bool operator == (FakeEnum a, FakeEnum b) { 
    return object.Equals(a,b);
}
public static bool operator != (FakeEnum a, FakeEnum b) { 
    return !object.Equals(a,b);
}
草莓味的萝莉 2024-08-19 20:23:59

object.equals 调用对象的 == 运算符(这将调用 object.equals 方法,该方法将调用对象(这将调用 ... )),剩下的就是堆栈溢出。

它调用对象的 equals 方法来测试底层整数值,以模拟枚举实例的行为方式。

object.equals calls the object's == operator (which would call the object.equals method which would call the objects (which would call ... ) ) and all you'd be left with is a stack overflow.

it calls the object's equals method to test the underlying integer value to simulate how an enum instance would behave.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文