Incorrect value in flag enum

Solved: this has to with arguably a bug in C#'s compiler. See the notes.

EDIT: I originally thought the watch value was incorrect. It is correct. The variable’s value is incorrect.

See inline notes, which reflect the copy & pasted watch items.

RemObjects C# code (same project):

[FlagsAttribute]
public enum CSet
{
	sOne = 1,
	sTwo = 2,
	sThree = 3,
	sFour = 4
}...    

Oxygene code:

      var cs1: CSet := CSet.sOne;                 
// cs1	WPFApplication3.CSet.sOne WPFApplication3.CSet
      var cs2: CSet := CSet.sOne or CSet.sFour;   
// cs2	WPFApplication3.CSet.sOne | **WPFApplication3.CSet.sThree** | WPFApplication3.CSet.sFour WPFApplication3.CSet
      var ix1: CSet := cs1 and cs2;               
// ix1	WPFApplication3.CSet.sOne WPFApplication3.CSet
    
      if (CSet.sThree and cs2) <> 0 then
        MessageBox.Show('???');

Mouse-over variable reflects the same incorrect value for cs2.

Removing the integer definitions of the CSet members will result in cs2 being only "cs2 WPFApplication3.CSet.sFour WPFApplication3.CSet"

Setting the enum definition in Oxygene causes expected results.

Your flags use 1,2,3,4, they really should use 1,2,4,8 else they’ll overlap (same issue in c#).

Ok, this is what I found out. In C# you HAVE TO define the bits 1, 2, 4, 8 etc. of each enum, but in Oxygene you don’t. Oxygene’s compiler is smart enough to get it right for you. Kudos.

C# defaults to 0, 1,2,3 if you don’t specify values for flags (which makes no sense if it’s a flags, but for enums it’s fine), which will give some even odder results when using flags.

I just found that out, which is why it wasn’t behaving as I expected, I why I erroneously misassigned the enum values. Thank you.

I’ve arguably found a C# compiler bug that I should report to MS.

PMFJI - I doubt that MS will consider it a “bug” in C#. It’s just the way the language works. There is this perception that C# is supposed to prevent a dev from making mistakes such as this, but in my experience C# is riddled with problems - as a language - that create huge potential for devs to slip up.

Even more so when you take into account the popular misconception that it is more difficult to do so because it’s C# !

@Deltics, in this particular case, it’s a compiler bug, not a language bug. All compilers have them, including classic Delphi. My only experience that relates to what you’re saying has to do with .Net, not C#, which is its voracious appetite for memory. The “garbage collector handles everything so I don’t need to take any responsibility” is where programmers get tripped up and fall.

The first first code I wrote in C# was a translation of a routine in Delphi. In Delphi, it consumed 30 MB RAM. Under .Net, it crashed from out-of-memory on a 2 GB RAM machine. I had to learn how to code differently, and once I did, it worked fine. Coding under Oxygene would be identical to C# memory-wise as both execute on .Net.

I’m curious to know what bugs you’re referring to in the language (so that I can make sure I am aware of these caveats).

Perhaps I misunderstood the “problem” in C# ? The [Flags] attribute decorates an enum in a way that allows ToString to return more useful information, but it doesn’t change the operation of the enum type in the language, and I don’t think that an attribute can change the behaviour of the compiler either.

Without a specific “flags” or “set” type construct in the language, all you can do in C# is use an enum as if it were a flags or set. But it’s still an enum, and the incremental assignment of values in an enum unless specifically overridden is a by-design “feature”. There is no language feature for automatically producing a set of flags so by definition there cannot be a bug in that feature.

Note that you can use an enum as a set of flags by specifically overriding the values with powers of two, even without the [Flags] attribute (as I say, this attribute affects the output of ToString, nothing else, so a flags enum without the [Flags] attribute simply doesn’t get this variance in ToString output.

Or was there some other compiler “bug” that you were referring to ?

As for other language bugs, the ones that I have come across (so far) include:

  • the lack of virtual constructors, demanding the use of high risk, error prone reflection to invoke constructors via a type reference without any compile time checks on the validity of that code, should the constructors on the referenced class type ever change.

  • the lack of sub-range types, forcing the use of inappropriately general ordinal types and requiring additional, explicit range validation code to be written (anything that is required to be written can be forgotten to be written).

  • the simple fact that the language is so unnecessarily verbose (ironic given that this is a complaint leveled against the “begin” and “end” in Pascal, by { } devotees. There is so much repetition involved in the language (e.g. in constantly having to state the visibility of a member decl). ime Repetition and especially verbose repetition leads to pattern blindness (where the fact of an error is missed among the noise - not being able to see the tree for the forest) which leads to mistakes going unnoticed.

That’s just off the top of my head. :slight_smile: I’m sure there are others that have had me spitting tacks recently that I haven’t recalled.

Some of these perhaps might not be considered “bugs” so much as flaws in the language design, but when talking about shortcomings - actual or perceived - in a language, such flaws in the design are “bugs” to me. Or at least defects. :slight_smile: