• Michael R (unregistered)

    1

  • Bad-decision maker (unregistered) in reply to Michael R

    Oh no, status code 1... What was the meaning of that? I need to look up the code.

  • WTFGuy (unregistered)

    I'm going to go way out on a limb here and guess that this is the first elided line: Enum3 = FILE_NOT_FOUND; \\ assume ranmod white-spcing here

    I'm also hoping the guy just above me whose post is now hidden didn't make the same lame joke.

  • (nodebb)

    4

  • (nodebb)

    In C# there is a pretty easy rule of thumb:

    • If it's 10 cases or less, use a switch (expression in this case obviously).

    • If it's more than 10 cases, use a Dictionary.

    Reason is pretty simple, while the readability is the same, a Dictionary lookup only becomes worth it after 10 cases otherwise the switch is faster. And obviously a Dictionary has a lot of initial cost as well, including generating heap objects, which is another topic.

    Regarding the code-painting, well, people did this in the past, I never ever understood why and I'm coding since the 80s. It's ugly and usually it became a mess after a while, may it be different tab sizes, mixing tabs with spaces, other people NGAS or finally automatic refactoring tools messing everything up anyway.

    Oh and BTW, the fix in VS is simple (considering the formatting rules are not messed up as well, but on the standard defaults to apply with MS style recommendations), just remove the last bracket } and write it again, press enter, everything should get aligned at least before the first non-whitespace character shows up. Maybe additional effort is required for stuff afterwards. Oh and obviously sending the angry mail to the dude that thought Bob Ross was a software developer costs a few seconds as well :-)

    Addendum 2023-05-31 07:46: I forgot to mention for all non net developers:

    .net has actually real generics; so there is no boxing/type erasure nonsense going on like in Java (for example). It's totally fine to use a dictionary with a value type, because .net has always generated concrete type implementations for value types and you won't end up with a ton of heap objects and even more boxing/unboxing like in most other languages. The KeyValuePair type used for the tuples is a value type as well however underlying representations of the hashmap itself are not and therefore you end up with a few large heap objects depending on with .net version you build your code.

  • (nodebb)

    enums 1-99 seem to be missing from the first block of code...

  • (nodebb)

    Oh, I forgot the enum handling itself:

    There are two best practices how to handle enums:

    1. Managed code

    In this case you should always address a enum by name. Exclusively. For DB persistence just use the EF ValueConverter. Obviously all serializer I know serialize by name as well by default.

    The reason is pretty simple: Refactoring. If you want another converter than the name converter, better write one for yourself with proper in/out mapping. I have a story there but this is a NDA topic which resulted in a criminal case in the end.

    1. Unmanaged code

    The obvious question is: Where does the underlying type has it uses?

    And the answer is pretty obvious to everyone born before 1980, and those that read the title. Unmanaged marshalling and flags. That's by the way also the only reason why you can declare the underlying type since C# 2.0.

  • TheCPUWizard (unregistered)

    https://learn.microsoft.com/en-us/cpp/cpp/structured-exception-handling-c-cpp?view=msvc-170

  • (nodebb)

    The point about a C developer reluctantly using C# is hitting the nail on the head. He was also told to "use enums", the intention being each method "Foo" and "Bar" can have a corresponding "FooResponseCode" and "BarResponseCode", respectively, which would allow context-specific options. But in his stubbornness, the developer chose "malicious compliance": you want me to use enums, here you go!!...

  • Barry Margolin (github)

    Maybe the function with the switch statement came first, then they decided to turn all the magic numbers into an enum, but they didn't go back and fix the case statements.

  • (nodebb) in reply to TheCPUWizard

    To be fair: Result codes are not error codes (obviously the original code mixes both, but that is to be expected here).

    You should never abuse exceptions for result codes. You should never abuse error codes for exceptions.

    Generally the Tester-Doer pattern should be used.

    public enum ResultCode
    {
      Result1,
      Result2
    }
    
    public string GetMessage(ResultCode code) =>
      TryGetMessage(code, out var message) ?
      message :
      throw new ArgumentOutOfBoundsException(nameof(code), code, default);
    
    public bool TryGetMessage([NotNullWhen(true)] out string? message)
    {
      switch(code)
      {
        case ResultCode.Result1: message = "Message 1"; return true;
        case ResultCode.Result2: message = "Message 2"; return true;
      }
    
      return false;
    }
    

    An for the ResultCodes UnknownError, Exception exceptions should be used while Success is useless.

    Addendum 2023-05-31 11:59: Well, that didn't work out as planned with the markdown :-) And because there's no editing feature, I post it again:

    public enum ResultCode
    {
      Result1,
      Result2
    }
    
    public string GetMessage(ResultCode code) =>
      TryGetMessage(code, out var message) ?
      message :
      throw new ArgumentOutOfBoundsException(nameof(code), code, default);
    
    public bool TryGetMessage([NotNullWhen(true)] out string? message)
    {
      switch(code)
      {
        case ResultCode.Result1: message = "Message 1"; return true;
        case ResultCode.Result2: message = "Message 2"; return true;
      }
    
      return false;
    }
    
  • (nodebb)

    Report because DailyWTF seem to have a very picky, unforgiving MD parser and there is no way to fix it :)

    To be fair: Result codes are not error codes (obviously the original code mixes both, but that is to be expected here).

    You should never abuse exceptions for result codes. You should never abuse error codes for exceptions.

    Generally the Tester-Doer pattern should be used.

    public enum ResultCode
    {
      Result1,
      Result2
    }
    
    public string GetMessage(ResultCode code) =>
      TryGetMessage(code, out var message) ?
      message :
      throw new ArgumentOutOfBoundsException(nameof(code), code, default);
    
    public bool TryGetMessage([NotNullWhen(true)] out string? message)
    {
      switch(code)
      {
        case ResultCode.Result1: message = "Message 1"; return true;
        case ResultCode.Result2: message = "Message 2"; return true;
      }
    
      return false;
    }
    

    An for the ResultCodes UnknownError, Exception exceptions should be used while Success is useless.

  • Your Name (unregistered)
    Comment held for moderation.
  • FTB (unregistered) in reply to MaxiTB
    Comment held for moderation.
  • (nodebb) in reply to MaxiTB

    .net has actually real generics; so there is no boxing/type erasure nonsense going on like in Java (for example).

    In Java, you'd make those descriptions be attached to the enum values themselves (probably as public (constant) fields in this case), so that instead of a big lookup table (whether by dictionary or switch) you'd just do code.description. It's a good way of modelling some kinds of expertise in a system.

  • (nodebb) in reply to MaxiTB

    .net has actually real generics; so there is no boxing/type erasure nonsense going on like in Java (for example).

    In Java, you'd make those descriptions be attached to the enum values themselves (probably as public (constant) fields in this case), so that instead of a big lookup table (whether by dictionary or switch) you'd just do code.description. It's a good way of modelling some kinds of expertise in a system.

  • (nodebb) in reply to MaxiTB

    If it's 10 cases or less, use a switch (expression in this case obviously).

    If it's more than 10 cases, use a Dictionary.

    There's a good case* for always using a switch. The compiler will tell you when there is a case missing. Well, it will in Swift. Maybe it doesn't in C♯.

    • sorry about the pun.
  • (nodebb) in reply to jeremypnet

    In .net enums are really value type enums not just reference type with syntactical sugar.

    For that reason it would make no sense, because while the name has to be unique, the value does not and therefore there's not a 1:1 relation. And if you include flags, you have a real pickle. Plus there is a lot of valid business cases why you don't want to handle enum values explicitly and for example fall back to default states.

    So the comparison doesn't really work here ;-)

  • (nodebb) in reply to dkf

    Java doesn't really enums, as you said they are just reference types with syntactical sugar with properties representing the values. In C# (or C/C++) enums have always been value types and you generally extend sealed value types with extension methods (I don't think Java doesn't even have extension methods yet).

    The lookup was an example; generally you use converters/mappers between layers because it's a really bad idea to have the same types on both your data layer and your API layer. And when it comes to a presentation layer, they way to go is localization anyway which in .net is done via the ResourceManager.

    In the old days of .net 1.0 devs used the [Description] attribute but meta information packing like that has fallen out of favor decades ago, because it's a pain to test compared to a converter/mapper. And obviously it's pretty useless approach when it comes to localization.

    Finally, keep in mind that most low level objects in .net implement obviously the tester-doer pattern, so a dictionary lookup results in a one-liner for those following best practices:

    public static bool TryGetMessage(ResultCode code, [NotNullWhen(true)] out string? message) =>
      _values.TryGetValue(code, out var message);
    
    private static readonly Dictionary<ResultCode, string> _values = new
    {
      { ResultCode.Result1, "Message 1" },
      { ResultCode.Result2, "Message 2" }
    };
    
  • (nodebb) in reply to MaxiTB

    Java doesn't really enums

    It's not a "real" enum because it doesn't work in exactly the way you think enums ought to? I guess that's a position you can take if you feel like it.

  • (nodebb) in reply to dkf

    The type enum comes from C and while it wasn't part of the initial language spec, exists as part of the language since at least the 80s. And enum is a integer value type. And it has been in all strongly typed languages - they only strongly language I know doesn't correctly implement enums is Java because it's just a reference type with syntactical sugar completely negating the point of an enum in the first place.

  • Craig (unregistered) in reply to MaxiTB
    Comment held for moderation.

Leave a comment on “Exceptional Descriptions”

Log In or post as a guest

Replying to comment #:

« Return to Article