Поддельный enum в C # - PullRequest
       29

Поддельный enum в C #

0 голосов
/ 30 ноября 2009

Я пытаюсь использовать код из этой статьи: Создание поддельных перечислений , но я не могу понять, почему он не работает.

Этот код:

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);

У меня просто закончились идеи - что мне не хватает, и что генерирует исключение при использовании оригинального кода?

Ответы [ 3 ]

7 голосов
/ 30 ноября 2009

Это бит:

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 нуждается в переопределении, если у вас действительно нет двух отдельных объектов с одинаковым значением (например, из-за сериализации, которая в любом случае будет странной ).

5 голосов
/ 30 ноября 2009

Я сам на самом деле не пробовал, но операции == и! = Определенно не реализованы правильно. Должно быть:

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);
}
1 голос
/ 02 декабря 2009

object.equals вызывает оператор объекта == (который будет вызывать метод object.equals, который будет вызывать объекты (который будет вызывать ...)), и все, что вам останется, это переполнение стека.

он вызывает метод equals объекта для проверки базового целочисленного значения, чтобы имитировать поведение экземпляра enum.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...