Jul2012
5

Enum types, FlagsAttribute & Zero value – Part 2

by nmgomes

In my previous post I wrote about why you should pay attention when using enum value Zero.

After reading that post you are probably thinking like Benjamin Roux: Why don’t you start the enum values at 0x1?

Well I could, but doing that I lose the ability to have Sync and Async mutually exclusive by design. Take a look at the following enum types:

[Flags]public enum OperationMode1{    Async = 0x1,    Sync = 0x2,    Parent = 0x4}[Flags]public enum OperationMode2{    Async = 0x0,    Sync = 0x1,    Parent = 0x2}

To achieve mutually exclusion between Sync and Async values using OperationMode1 you would have to operate both values:

protected void CheckMainOperarionMode(OperationMode1 mode){    switch (mode)    {        case (OperationMode1.Async | OperationMode1.Sync | OperationMode1.Parent):        case (OperationMode1.Async | OperationMode1.Sync):            throw new InvalidOperationException("Cannot be Sync and Async simultaneous");            break;        case (OperationMode1.Async | OperationMode1.Parent):        case (OperationMode1.Async):            break;        case (OperationMode1.Sync | OperationMode1.Parent):        case (OperationMode1.Sync):            break;        default:            throw new InvalidOperationException("No default mode specified");    }}

but this is a by design constraint in OperationMode2. Why? Simply because 0x0 is the neutral element for the bitwise OR operation.

Knowing this singularity, replacing and simplifying the previous method, you get:

protected void CheckMainOperarionMode(OperationMode2 mode){    switch (mode)    {        case (OperationMode2.Sync | OperationMode2.Parent):        case (OperationMode2.Sync):            break;        case (OperationMode2.Parent):        default:            break;    }

This means that:

  • if both Sync and Async values are specified Sync value always win (Zero is the neutral element for bitwise OR operation)
  • if no Sync value specified, the Async method is used.

Here is the final method implementation:

protected void CheckMainOperarionMode(OperationMode2 mode){    if (mode & OperationMode2.Sync == OperationMode2.Sync)    {    } else {     }}

All content above prove that Async value (0x0) is useless from the arithmetic perspective, but, without it we lose readability.

The following IF statements are logically equals but the first is definitely more readable:

if (OperationMode2.Async | OperationMode2.Parent){}if (OperationMode2.Parent){ }

Here’s another example where you can see the benefits of 0x0 value, the default value can be used explicitly.

    <my:Control runat="server" Mode="Async,Parent">    <my:Control runat="server" Mode="Parent">

Filed in: .NET | ASP.NET

Jul2012
4

Enum types, FlagsAttribute & Zero value

by nmgomes

We all know about Enums types and use them every single day. What is not that often used is to decorate the Enum type with the FlagsAttribute.

When an Enum type has the FlagsAttribute we can assign multiple values to it and thus combine multiple information into a single enum.

The enum values should be a power of two so that a bit set is achieved.

Here is a typical Enum type:

public enum OperationMode
{
    /// <summary>
    /// No operation mode
    /// </summary>
    None = 0,
    /// <summary>
    /// Standard operation mode
    /// </summary>
    Standard = 1,
    /// <summary>
    /// Accept bubble requests mode
    /// </summary>
    Parent = 2
}

In such scenario no values combination are possible. In the following scenario a default operation mode exists and combination is used:

[Flags]
public enum OperationMode
{
    /// <summary>
    /// Asynchronous operation mode
    /// </summary>
    Async = 0,
    /// <summary>
    /// Synchronous operation mode
    /// </summary>
    Sync = 1,
    /// <summary>
    /// Accept bubble requests mode
    /// </summary>
    Parent = 2
}

Now, it’s possible to do statements like:

[DefaultValue(OperationMode.Async)] [TypeConverter(typeof(EnumConverter))] public OperationMode Mode { get; set; } /// <summary> /// Gets a value indicating whether this instance supports request from childrens. /// </summary> public bool IsParent { get { return (this.Mode & OperationMode.Parent) == OperationMode.Parent; } }

or

switch (this.Mode) { case OperationMode.Sync | OperationMode.Parent: Console.WriteLine("Sync,Parent"); break;

[…]

 

But there is something that you should never forget: Zero is the absorber element for the bitwise AND operation.

So, checking for OperationMode.Async (the Zero value) mode just like the OperationMode.Parent mode makes no sense since it will always be true:

(this.Mode & 0x0) == 0x0

Instead, inverse logic should be used: OperationMode.Async = !OperationMode.Sync

public bool IsAsync
{
    get { return (this.Mode & ContentManagerOperationMode.Sync) != ContentManagerOperationMode.Sync; }
}

or

public bool IsAsync
{
    get { return (int)this.Mode == 0; }
}

[Begin: Edit]

Some readers suggested to use the Enum.HasFlag method. Although it’s another valid approach it’s also widely accepted that this method has some performance issues related an internal box/unboxing.

Use it when performance is not a problem (I see this method mostly used by rookie developers).

[End: Edit]

Final Note:

Benefits

Allow multiple values combination

The above samples snippets were taken from an ASP.NET control and enabled the following markup usage:

<my:Control runat="server" Mode="Sync,Parent">

Drawback

Zero value is the absorber element for the bitwise AND operation

Be very carefully when evaluating the Zero value, either evaluate the enum value as an integer or use inverse logic.

Filed in: ASP.NET | .NET

Oct2010
14

ASP.NET Controls - System.Web.UI.HtmlControls.HtmlButton client click hits the server twice

by nmgomes

Hi all,

At work we have about 5000 PC's that are mainly our commercial network. All those PC use intranet services and web applications.

Until a few months ago IE6 was our corporate browser (yep) but we ended moving to IE8.

A few days ago someone came to me saying that their application appears to have some problem because every time they click some HTML buttons the server gets two hits.

Also they are able to say that this didn't happen when they used the IE6.

In the faulty application the buttons that trigger two posts were System.Web.UI.HtmlControls.HtmlButton controls with Click event handlers registered.

After some research I found that the default type attribute value for HTML BUTTON element has changed in IE8 and later (here).

  • In IE7 and earlier the default value is 'button'
  • In IE8 and later the default value is 'submit'

This changed in browser default behavior was not reflected in the Server-Control that renders it: it doesn't set the type attribute value to button when a postback is required.

Without such change, every time we attached a Click event handler to a HtmlButton we endup with two posts: one triggered by the _doPostback function and another from the form itself (caused by the default type='submit' value.).

I easily bypass this problem by setting the type attribute value to 'button' in my base control.

Even so, I think that this change should be done by the framework itself when a postback is required in a HtmlButton.

After some 'reflection' I propose changing the System.Web.UI.Util.WriteOnClickAttribute method to do the job.

Such change would ensure the some behavior independent of the browser version.

If you have another workaround or you think I'm completely wrong please let me know.

Also if you think this is a real problem that should be solved then visit this Connect entry I create.

Filed in: ASP.NET