By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
446,367 Members | 1,281 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 446,367 IT Pros & Developers. It's quick & easy.

Rationale behind int to enum casts

P: n/a
Hi there

Spending half an hour searching through the archive I haven't found a
rationale for the following behavior.

using System;

// note the missing Flags attribute
enum Color
{
Red,
Green,
Blue
}

class Whatever
{
static void Main()
{
// The following cast succeeds although the
// value 42 does not exist.
Color color = (Color) 42;
Console.WriteLine( "{0}", color );
}
}

I believe it would make my and other peoples life easier if that cast
failed. Moreover, the framework does not even seem to offer a function
to implement this directly. I have to roll my own, using
Enum.IsDefined().

What is the rationale for this?

Thanks & Regards,

Andreas
Nov 15 '05 #1
Share this Question
Share on Google+
21 Replies


P: n/a
Try to look at IConvertible

"Andreas Huber" <ah****@gmx.net> schrieb im Newsbeitrag
news:3e**************************@posting.google.c om...
Hi there

Spending half an hour searching through the archive I haven't found a
rationale for the following behavior.

using System;

// note the missing Flags attribute
enum Color
{
Red,
Green,
Blue
}

class Whatever
{
static void Main()
{
// The following cast succeeds although the
// value 42 does not exist.
Color color = (Color) 42;
Console.WriteLine( "{0}", color );
}
}

I believe it would make my and other peoples life easier if that cast
failed. Moreover, the framework does not even seem to offer a function
to implement this directly. I have to roll my own, using
Enum.IsDefined().

What is the rationale for this?

Thanks & Regards,

Andreas

Nov 15 '05 #2

P: n/a
Hi Andreas,

Your enum is really an int.
And the framework won't look if it is defined or not because of performance
issue.
Imagine this

enum Tubo
{
Alfa = 11,
Beta = 44
}

public void SomeMethod(int j)
{
int i = 5 * j;
Tubo t = (Tubo)i;
}

It would be a big performance hit if runtime checks if it is valid or not...

--
Miha Markic - RightHand .NET consulting & software development
miha at rthand com

"Andreas Huber" <ah****@gmx.net> wrote in message
news:3e**************************@posting.google.c om...
Hi there

Spending half an hour searching through the archive I haven't found a
rationale for the following behavior.

using System;

// note the missing Flags attribute
enum Color
{
Red,
Green,
Blue
}

class Whatever
{
static void Main()
{
// The following cast succeeds although the
// value 42 does not exist.
Color color = (Color) 42;
Console.WriteLine( "{0}", color );
}
}

I believe it would make my and other peoples life easier if that cast
failed. Moreover, the framework does not even seem to offer a function
to implement this directly. I have to roll my own, using
Enum.IsDefined().

What is the rationale for this?

Thanks & Regards,

Andreas

Nov 15 '05 #3

P: n/a
On Wed, 26 Nov 2003 14:49:38 +0100, "Miha Markic" <miha at rthand com>
wrote:
It would be a big performance hit if runtime checks if it is valid or not...


Only if you constantly convert from int to enum which you shouldn't be
doing anyway because it defeats the point of having enums in the first
place. At least in debug mode, the compiler or framework should check
automatically that the value is actually valid.

Again, the whole point of using enums instead of ints is type safety.
I agree with Andreas that this behaviour is bizarre and should be
fixed, performance hit or not.
--
http://www.kynosarges.de
Nov 15 '05 #4

P: n/a
Hi,

"Christoph Nahr" <ch************@kynosarges.de> schrieb im Newsbeitrag
news:po********************************@4ax.com...
On Wed, 26 Nov 2003 14:49:38 +0100, "Miha Markic" <miha at rthand com>
wrote:

I agree with Andreas that this behaviour is bizarre and should be
fixed, performance hit or not.


There is nothing to "fix". This is a documented behaviour.

From MSDN:
MSDN .NET Framework General Reference
Value Type Usage Guidelines

<quote>
Do not assume that enum arguments will be in the defined range. It is valid
to cast any integer value into an enum even if the value is not defined in
the enum. Perform argument validation as illustrated in the following code
example.
[Visual Basic]
Public Sub SetColor(newColor As Color)
If Not [Enum].IsDefined(GetType(Color), newColor) Then
Throw New ArgumentOutOfRangeException()
End If
End Sub
[C#]
public void SetColor (Color color)
{
if (!Enum.IsDefined (typeof(Color), color)
throw new ArgumentOutOfRangeException();
}
</quote>

hth
Uwe
Nov 15 '05 #5

P: n/a
Enums are used both for a set of enumerated values, and for bit fields. In
the bit fields case, you need to be able to represent values that aren't
equal to one of the defined constants.

You can use the static methods on the Enum class to see if a specific value
is equal to one of the predefined constant values.

--
Eric Gunnerson

Visit the C# product team at http://www.csharp.net
Eric's blog is at http://blogs.gotdotnet.com/ericgu/

This posting is provided "AS IS" with no warranties, and confers no rights.
"Andreas Huber" <ah****@gmx.net> wrote in message
news:3e**************************@posting.google.c om...
Hi there

Spending half an hour searching through the archive I haven't found a
rationale for the following behavior.

using System;

// note the missing Flags attribute
enum Color
{
Red,
Green,
Blue
}

class Whatever
{
static void Main()
{
// The following cast succeeds although the
// value 42 does not exist.
Color color = (Color) 42;
Console.WriteLine( "{0}", color );
}
}

I believe it would make my and other peoples life easier if that cast
failed. Moreover, the framework does not even seem to offer a function
to implement this directly. I have to roll my own, using
Enum.IsDefined().

What is the rationale for this?

Thanks & Regards,

Andreas

Nov 15 '05 #6

P: n/a
On Wed, 26 Nov 2003 17:23:15 +0100, "Uwe Hafner"
<Sp********@NOSPAM.de> wrote:
There is nothing to "fix". This is a documented behaviour.


Yes... we disagree with that documented behaviour, and consider it
broken, hence we want a "fix".
--
http://www.kynosarges.de
Nov 15 '05 #7

P: n/a
On Wed, 26 Nov 2003 12:54:03 -0800, "Eric Gunnerson [MS]"
<er****@online.microsoft.com> wrote:
Enums are used both for a set of enumerated values, and for bit fields. In
the bit fields case, you need to be able to represent values that aren't
equal to one of the defined constants.


But bit field enums are always indicated by the [Flags] attribute,
correct? It should be easy enough to auto-generate a conversion check
if that attribute is not present.
--
http://www.kynosarges.de
Nov 15 '05 #8

P: n/a
Hi Chris,

"Christoph Nahr" <ch************@kynosarges.de> wrote in message
news:id********************************@4ax.com...
On Wed, 26 Nov 2003 12:54:03 -0800, "Eric Gunnerson [MS]"
<er****@online.microsoft.com> wrote:
Enums are used both for a set of enumerated values, and for bit fields. Inthe bit fields case, you need to be able to represent values that aren't
equal to one of the defined constants.


But bit field enums are always indicated by the [Flags] attribute,
correct? It should be easy enough to auto-generate a conversion check
if that attribute is not present.


Not really.
FlagsAttribute is just a descriptor - used by some function (for text output
(ToString) if I remember correctly).
You can safely use enums for flags without FlagsAttribute.

--
Miha Markic - RightHand .NET consulting & software development
miha at rthand com
Nov 15 '05 #9

P: n/a
Eric,
Enums are used both for a set of enumerated values, and for bit fields. In
the bit fields case, you need to be able to represent values that aren't
equal to one of the defined constants.


I know, I'm wondering why C# behaves this way __even if I don't put a
Flags attribute__ on my enum. This doesn't make a lot of sense to
me...

Thanks & Regards,

Andreas
Nov 15 '05 #10

P: n/a
ah****@gmx.net (Andreas Huber) wrote in message news:<3e**************************@posting.google. com>...
I believe it would make my and other peoples life easier if that cast
failed. Moreover, the framework does not even seem to offer a function
to implement this directly. I have to roll my own, using
Enum.IsDefined().


I had a similar discussion about this a while back, so the following
may be of interest to you:
http://groups.google.com/groups?hl=e...ing.google.com
[watch out for wordwrap]

Regards,

Matt
Nov 15 '05 #11

P: n/a
On Thu, 27 Nov 2003 09:50:23 +0100, "Miha Markic" <miha at rthand com>
wrote:
FlagsAttribute is just a descriptor - used by some function (for text output
(ToString) if I remember correctly).
You can safely use enums for flags without FlagsAttribute.


Okay, but who does this? IMO it would be safe to restrict the language
definition so that Flags is required for bitwise combinable flags. The
compiler could then react to the absence of the attribute by providing
a custom base-type-to-enum conversion with range-checking code.
--
http://www.kynosarges.de
Nov 15 '05 #12

P: n/a
I've always liked Delphi sets :)

--
Miha Markic - RightHand .NET consulting & software development
miha at rthand com

"Christoph Nahr" <ch************@kynosarges.de> wrote in message
news:8v********************************@4ax.com...
On Thu, 27 Nov 2003 09:50:23 +0100, "Miha Markic" <miha at rthand com>
wrote:
FlagsAttribute is just a descriptor - used by some function (for text output(ToString) if I remember correctly).
You can safely use enums for flags without FlagsAttribute.


Okay, but who does this? IMO it would be safe to restrict the language
definition so that Flags is required for bitwise combinable flags. The
compiler could then react to the absence of the attribute by providing
a custom base-type-to-enum conversion with range-checking code.
--
http://www.kynosarges.de

Nov 15 '05 #13

P: n/a

"Christoph Nahr" <ch************@kynosarges.de> wrote in message
news:8v********************************@4ax.com...
On Thu, 27 Nov 2003 09:50:23 +0100, "Miha Markic" <miha at rthand com>
wrote:
FlagsAttribute is just a descriptor - used by some function (for text output(ToString) if I remember correctly).
You can safely use enums for flags without FlagsAttribute.
Okay, but who does this? IMO it would be safe to restrict the language
definition so that Flags is required for bitwise combinable flags. The
compiler could then react to the absence of the attribute by providing
a custom base-type-to-enum conversion with range-checking code.


Which is fine until you have to use a VB, or C++, or any other language
library and cannot perform bitwise combinations because that language
doesn't force the Flags attribute. It cannot be a single langauge thing, it
would have to be defined in the CLS. If you cannot rely on your enums being
created IN C#, so you cannot rely on a language specification to handle this
situation, the runtime and all assocaited languages would have to use it.
And I personally don't want to have to cast every enum to int to perform a
bitwise operation and cast back to the enum.
Frankly, I consider the lack of member value checking a nicety. There are
times when using a bit flagged set of options where you will have flags set
that aren't considred in the current version, but are irrelevent and can be
ignored, having to write code to mask out all possible invalid flags is a
pain and will result in incorrect flags set when persisted.
--
http://www.kynosarges.de

Nov 15 '05 #14

P: n/a
Daniel,
Okay, but who does this? IMO it would be safe to restrict the language
definition so that Flags is required for bitwise combinable flags. The
compiler could then react to the absence of the attribute by providing
a custom base-type-to-enum conversion with range-checking code.
Which is fine until you have to use a VB, or C++, or any other language
library and cannot perform bitwise combinations because that language
doesn't force the Flags attribute. It cannot be a single langauge thing, it
would have to be defined in the CLS.


Easy: Enums lacking a Flags attribute would not be CLS compliant. It's
the same situation with unsigned/signed ints: The whole .NET framework
uses only signed ints. However, C#-only stuff can use unsigned ints,
which means that such code cannot be consumed by languages like VB.

Of course the CLR would have to support two types of enums:
- A strict one that is always checked and thus only usable for
ordinary enums.
- A nonstrict one that is never checked and thus usable for both
ordinary and bitflagged enums.
Depending on the language, either the strict or the non-strict one is
emitted by default. In C# this would be the strict variant, adding a
Flags attribute would make it a non-strict one what also makes it
consumeable by other languages.
And I personally don't want to have to cast every enum to int to perform a
bitwise operation and cast back to the enum.
Frankly, I consider the lack of member value checking a nicety. There are
times when using a bit flagged set of options where you will have flags set
that aren't considred in the current version, but are irrelevent and can be
ignored, having to write code to mask out all possible invalid flags is a
pain and will result in incorrect flags set when persisted.


The checking would only be done for enums lacking the Flags attribute,
enums with the Flags attribute would not be checked. This way the
programmer has full control.

Regards,

Andreas
Nov 15 '05 #15

P: n/a

"Andreas Huber" <ah****@gmx.net> wrote in message
news:3e*************************@posting.google.co m...
Daniel,
Okay, but who does this? IMO it would be safe to restrict the language
definition so that Flags is required for bitwise combinable flags. The
compiler could then react to the absence of the attribute by providing
a custom base-type-to-enum conversion with range-checking code.
Which is fine until you have to use a VB, or C++, or any other language
library and cannot perform bitwise combinations because that language
doesn't force the Flags attribute. It cannot be a single langauge thing, it would have to be defined in the CLS.


Easy: Enums lacking a Flags attribute would not be CLS compliant. It's
the same situation with unsigned/signed ints: The whole .NET framework
uses only signed ints. However, C#-only stuff can use unsigned ints,
which means that such code cannot be consumed by languages like VB.

Of course the CLR would have to support two types of enums:
- A strict one that is always checked and thus only usable for
ordinary enums.
- A nonstrict one that is never checked and thus usable for both
ordinary and bitflagged enums.
Depending on the language, either the strict or the non-strict one is
emitted by default. In C# this would be the strict variant, adding a
Flags attribute would make it a non-strict one what also makes it
consumeable by other languages.


Since an enum is an int(or other basic type) at its heart, you can't even
guarentee it was generated in a .NET language. The int easly could be
produced by unmanaged C++, VB6, TSQL, Delphi, Assembly, SmallTalk, whatever,
and stored in a database. Its not always possible to assume the enum was
sourced from .NET, it adds another point of failure to your application.
Plus, don't you think this is getting a little complex? Two enum types,
different rules, different rules for the flag type...I thought part of the
point of C# was to avoid the insane amount of uselss complexity C++ hoisted
on us. This would not exact help simplicity. There could also be a set of
complex rule attributes specifying that value a can only be set if value b
isn't, etc, but do we need that level of language complexity IN enums? I
don't hear anyone wanting that, and I think it would be far more useful.
And I personally don't want to have to cast every enum to int to perform a bitwise operation and cast back to the enum.
Frankly, I consider the lack of member value checking a nicety. There are times when using a bit flagged set of options where you will have flags set that aren't considred in the current version, but are irrelevent and can be ignored, having to write code to mask out all possible invalid flags is a pain and will result in incorrect flags set when persisted.


The checking would only be done for enums lacking the Flags attribute,
enums with the Flags attribute would not be checked. This way the
programmer has full control.


Which would result in ALOT of enums being marked as Flags(or an unstrict
attribute) because the programmer cannot allow member checking in his
situtation, either because they need an empty state in the enum or the enum
value is generated outside of the runtime. Again, even assuming new CLS
rules, any time the enum value is produced outside of an enum, you cannot
assume that enum value is valid and therefore would either a) have to check
it before casting to enum, b) risk suffering an exception from not checking
it, thereby slowing down or possibly breaking code. I don't think I want to
have to write a try{} block around every enum assignement I do, and doing my
own checking defeats the purpose of the runtime performing the checks for
me.

I just don't want to have to write code like this(pseudocode):

MyEnum myEnum;
int enumValue = SomeoneElsesFunctionThatReturnsInt();
//I'd rather not get a surprise exception, why waste the cycles?
//not to mention, the code would be identical if the runtime did no checks
if (MyEnum.IsDefined(enumValue))
myEnum = (MyEnum)enumValue;
else
myEnum = MyEnum.Default;
where the system assignement to myEnum basically does this:

if (MyEnum.IsDefined(value))
return new myEnum;
else
throw new InvalidEnumValueException();

Why do we need two calls to IsDefined here? I mean, in the end this will
just result in slower code all around and probably more errors. Is there
really any benefit if I still have to check the value before casting to
avoid a useless exception? Considering, in this case, the range of
non-exceptional values is finite, avoiding the exception would be
responsible, imho. So exception or no, you will have to do the check if you
want to write decent code...what is the benefit?

Regards,

Andreas

Nov 15 '05 #16

P: n/a
Daniel,
Since an enum is an int(or other basic type) at its heart, you can't even
guarentee it was generated in a .NET language. The int easly could be
produced by unmanaged C++, VB6, TSQL, Delphi, Assembly, SmallTalk, whatever,
and stored in a database. Its not always possible to assume the enum was
sourced from .NET,
I fail to see what the underlying layout of a class or an enum has to
do with invariant enforcement. Just like a class an enum is simply an
abstract concept, nothing more nothing less.
I also don't to see why the source of an object (data base, file,
interlanguage call, etc.) should have an impact on whether the
invariants should be enforced or not.
When I save an enum into an external store and reload it later, I'll
just as much expect that the enum will have a legal value as I expect
an object of *any* other type to have a legal value. E.g. If I convert
a string into a DateTime object I'll expect that the object is in a
legal state after conversion or an exception being thrown otherwise.
And this is exactly what DateTime.Parse() does.
Why should an int to enum conversion behave differently than a string
to DateTime conversion? In both cases the problem is the same: that an
object of the source type has many more legal states than an object of
the destination type.
it adds another point of failure to your application.
From what you have written so far, I assume that you would simply
allow the invalid enum value be processed and/or displayed by your
program. While I can imagine situations where it is perfectly
reasonable to do so (ignoring a problem and grinding on rather than
dealing with it), I don't think that this is good practice in most
real-world applications. The reasons are as follows:

- Most people prefer a program that refuses to perform an operation
when it detects a problem over a program that produces incorrect
results. This is/was the case in all projects I was involved in
- If you allow enums to have invalid values your *whole* program must
be able to deal with them, i.e. similar code must be spread
everywhere. I'd rather avoid this when I can make the checks once,
i.e. in the persistence or interfacing layer
Plus, don't you think this is getting a little complex? Two enum types,
different rules, different rules for the flag type...I thought part of the
point of C# was to avoid the insane amount of uselss complexity C++ hoisted
on us.
Well, the world is complex, isn't it ;-)? Seriously, wasn't the single
most important argument for C# and .NET that the code is managed, i.e.
that many common programmer errors can and will be detected by the
runtime?
I'll ignore the C++ part for the moment as that would be worth a
thread of its own.
This would not exact help simplicity. There could also be a set of
complex rule attributes specifying that value a can only be set if value b
isn't, etc, but do we need that level of language complexity IN enums? I
don't hear anyone wanting that, and I think it would be far more useful.
What is so complex about having to put a Flags attribute on an enum
that you don't want to have checked? Plus, either the compiler could
help you in many situations or you'd find out very soon when you test
your code for the first time. How this is implemented is of little
importance.
The checking would only be done for enums lacking the Flags attribute,
enums with the Flags attribute would not be checked. This way the
programmer has full control.


Which would result in ALOT of enums being marked as Flags(or an unstrict
attribute) because the programmer cannot allow member checking in his
situtation, either because they need an empty state in the enum or the enum
value is generated outside of the runtime.


If you need an empty state, give the enum one. Period. I still fail to
see what the enum value being generated outside the runtime has to do
with invariant enforcement.
Again, even assuming new CLS
rules, any time the enum value is produced outside of an enum, you cannot
assume that enum value is valid and therefore would either a) have to check
it before casting to enum, b) risk suffering an exception from not checking
it, thereby slowing down or possibly breaking code.
This is such a common misconception. Why do you check the enum to
avoid the exception? As you can expect the exception to only be thrown
very rarely, the checking to avoid the exception will actually slow
the code down, because try blocks are a lot faster than ifs, as long
as no exception is thrown.
I don't think I want to
have to write a try{} block around every enum assignement I do, and doing my
own checking defeats the purpose of the runtime performing the checks for
me.
Dito.
I just don't want to have to write code like this(pseudocode):

MyEnum myEnum;
int enumValue = SomeoneElsesFunctionThatReturnsInt();
//I'd rather not get a surprise exception, why waste the cycles?
//not to mention, the code would be identical if the runtime did no checks
if (MyEnum.IsDefined(enumValue))
myEnum = (MyEnum)enumValue;
else
myEnum = MyEnum.Default;
where the system assignement to myEnum basically does this:

if (MyEnum.IsDefined(value))
return new myEnum;
else
throw new InvalidEnumValueException();

Why do we need two calls to IsDefined here? I mean, in the end this will
just result in slower code all around and probably more errors.
We don't! See above.
Is there
really any benefit if I still have to check the value before casting to
avoid a useless exception? Considering, in this case, the range of
non-exceptional values is finite, avoiding the exception would be
responsible, imho. So exception or no, you will have to do the check if you
want to write decent code...what is the benefit?


And I claim exactly the opposite, decent code never checks to avoid
exceptions that occur only rarely.
Moreover such errors (an enum having an invalid value) can almost
never be dealt with locally. More often than not the error has to be
passed up the call chain over several stack frames. This is exactly
what exceptions were invented for.

Regards,

Andreas
Nov 15 '05 #17

P: n/a

"Andreas Huber" <ah****@gmx.net> wrote in message
news:3e**************************@posting.google.c om...
Daniel,
Since an enum is an int(or other basic type) at its heart, you can't even
guarentee it was generated in a .NET language. The int easly could be
produced by unmanaged C++, VB6, TSQL, Delphi, Assembly, SmallTalk, whatever, and stored in a database. Its not always possible to assume the enum was
sourced from .NET,
I fail to see what the underlying layout of a class or an enum has to
do with invariant enforcement. Just like a class an enum is simply an
abstract concept, nothing more nothing less.
I also don't to see why the source of an object (data base, file,
interlanguage call, etc.) should have an impact on whether the
invariants should be enforced or not.
When I save an enum into an external store and reload it later, I'll
just as much expect that the enum will have a legal value as I expect
an object of *any* other type to have a legal value. E.g. If I convert
a string into a DateTime object I'll expect that the object is in a
legal state after conversion or an exception being thrown otherwise.
And this is exactly what DateTime.Parse() does.


And they are introducing DateTime.TryParse() for just that reason, sometimes
an exception is just not acceptable.
Why should an int to enum conversion behave differently than a string
to DateTime conversion? In both cases the problem is the same: that an
object of the source type has many more legal states than an object of
the destination type.
it adds another point of failure to your application.
From what you have written so far, I assume that you would simply
allow the invalid enum value be processed and/or displayed by your
program. While I can imagine situations where it is perfectly
reasonable to do so (ignoring a problem and grinding on rather than
dealing with it), I don't think that this is good practice in most
real-world applications. The reasons are as follows:

- Most people prefer a program that refuses to perform an operation
when it detects a problem over a program that produces incorrect
results. This is/was the case in all projects I was involved in
- If you allow enums to have invalid values your *whole* program must
be able to deal with them, i.e. similar code must be spread
everywhere. I'd rather avoid this when I can make the checks once,
i.e. in the persistence or interfacing layer

It would depend on what the enums meaning was. If the enum specified an
operation, or a list entry, etc, then no I wouldn't. However, if it is just
an option and no option is as valid as all options, then yes I would. When I
load an enum, if the enum must have a value I do the checking. If it is
acceptable for it to be empty(granted, these are usually Flags decorated
enums), then I leave it be.
Plus, don't you think this is getting a little complex? Two enum types,
different rules, different rules for the flag type...I thought part of the point of C# was to avoid the insane amount of uselss complexity C++ hoisted on us.


Well, the world is complex, isn't it ;-)? Seriously, wasn't the single
most important argument for C# and .NET that the code is managed, i.e.
that many common programmer errors can and will be detected by the
runtime?

Yes, followed closely by increased simplicity. I'll ignore the C++ part for the moment as that would be worth a
thread of its own.
This would not exact help simplicity. There could also be a set of
complex rule attributes specifying that value a can only be set if value b isn't, etc, but do we need that level of language complexity IN enums? I
don't hear anyone wanting that, and I think it would be far more useful.
What is so complex about having to put a Flags attribute on an enum
that you don't want to have checked? Plus, either the compiler could
help you in many situations or you'd find out very soon when you test
your code for the first time. How this is implemented is of little
importance.


Its semantically wrong, IMHO, to use Flags on an enum that is not a flagged.
I'd argue for a Unchecked attribute before I'd accept using Flags on a
non-flagged enum.
The checking would only be done for enums lacking the Flags attribute,
enums with the Flags attribute would not be checked. This way the
programmer has full control.
Which would result in ALOT of enums being marked as Flags(or an unstrict
attribute) because the programmer cannot allow member checking in his
situtation, either because they need an empty state in the enum or the enum value is generated outside of the runtime.


If you need an empty state, give the enum one. Period. I still fail to
see what the enum value being generated outside the runtime has to do
with invariant enforcement.


While thats preferable, it doesn't mean its always possible or it is always
done(not all enums in the world are under my control, for example)
Again, even assuming new CLS
rules, any time the enum value is produced outside of an enum, you cannot assume that enum value is valid and therefore would either a) have to check it before casting to enum, b) risk suffering an exception from not checking it, thereby slowing down or possibly breaking code.
This is such a common misconception. Why do you check the enum to
avoid the exception? As you can expect the exception to only be thrown
very rarely, the checking to avoid the exception will actually slow
the code down, because try blocks are a lot faster than ifs, as long
as no exception is thrown.


Because if I did not generate the enum value, there is NO reason to assume
the exception will be uncommon. If the enum is sourced by a non .NET
language or whatever, there is no way to assume it is correct. Just as if
you were given a file name, do you jsut open the file and catch the
exception if it comes? or do you call File.Exists() to check while still
handling exceptions as they come.
It depends heavily on the context, IMHO. If you are dealing with ONE file,
then just relying on the exception is ok, if you are dealing with many, you
have no idea how common the issue will be and cannot rely on the exception
being rare. It could happen 500000 times, you cannot tell at runtime.
In most cases, I consider enums to be singlar operations, but then again, in
most cases I consider files to be singlar operations too. This change could
potentially seriously cut back on flexibility.
I don't think I want to
have to write a try{} block around every enum assignement I do, and doing my own checking defeats the purpose of the runtime performing the checks for me.


Dito.
I just don't want to have to write code like this(pseudocode):

MyEnum myEnum;
int enumValue = SomeoneElsesFunctionThatReturnsInt();
//I'd rather not get a surprise exception, why waste the cycles?
//not to mention, the code would be identical if the runtime did no checks if (MyEnum.IsDefined(enumValue))
myEnum = (MyEnum)enumValue;
else
myEnum = MyEnum.Default;
where the system assignement to myEnum basically does this:

if (MyEnum.IsDefined(value))
return new myEnum;
else
throw new InvalidEnumValueException();

Why do we need two calls to IsDefined here? I mean, in the end this will
just result in slower code all around and probably more errors.


We don't! See above.
Is there
really any benefit if I still have to check the value before casting to
avoid a useless exception? Considering, in this case, the range of
non-exceptional values is finite, avoiding the exception would be
responsible, imho. So exception or no, you will have to do the check if you want to write decent code...what is the benefit?


And I claim exactly the opposite, decent code never checks to avoid
exceptions that occur only rarely.
Moreover such errors (an enum having an invalid value) can almost
never be dealt with locally. More often than not the error has to be
passed up the call chain over several stack frames. This is exactly
what exceptions were invented for.

I agree, I just don't think the runtime should be throwing the exception. If
there is need for an exception to be thrown, I'll do it. I wrote the code
and at times the runtime is a bit too invasive as it is, this would just
make it more so. There is a line where features for the common start to make
it too difficult to work in the environment for the uncommon, I think this
feature would be one. It would make .NET a much less interesting choice in
enough situations that it would dilute its value to me.

Perhaps an Enum static method equivilent to the DateTime method ParseExact
would be more appropriate? While it wouldn't be called ParseExact,
obviously, as it doesn't deal with strings, but it seems like it would solve
this problem without an issue, allow casts to operate as is(breaking
existing functionality is also unattractive), and add a static member that
throws an exception if the enum value is incorrect, maybe something like

struct Enum
{
//existing enum members
//Performs the same work as a cast
public static object GetEnum(Type enumType, int value);
//Performs the same work as a cast, however checks the enum
//and insures value is a valid type.
public static object GetEnumExact(Type enumType, int value);
//other overloads for possible underlying types. Unfortunatly
//generics cannot take System.Enum as a type constraint, so you are stuck
with a cast

}
The main advantage of this is it would allow both Flags and non-Flags
decorated enums to be validly converted in either situation. It can be that
in one case a Flags enum needs to be precise, but in others needs to be
loose. A specific rule using Flags potentially causes loss of flexibility.
Adding another attribute to the mix fixes that, but adds more complexity and
locks the enum's use to what the author of the enum wants. In some cases the
author cannot know how exactly the enum will be used outside of it being
Flags or a singular enum, or the enum will be of value in another situation.
This will allow the consumer to determine the specifics and help
reuseability. The consumer would have to be responsible for making sure that
it doesn't call a method that expects valid enums without a try\catch
block(or appropriate handling) if the consumer doesn't validate the enum.
This is a situation where adding attributes to a given instance would be of
value, a ValidatedInstanceAttribute or something. Regards,

Andreas

Nov 15 '05 #18

P: n/a
Daniel,
I fail to see what the underlying layout of a class or an enum has to
do with invariant enforcement. Just like a class an enum is simply an
abstract concept, nothing more nothing less.
I also don't to see why the source of an object (data base, file,
interlanguage call, etc.) should have an impact on whether the
invariants should be enforced or not.
When I save an enum into an external store and reload it later, I'll
just as much expect that the enum will have a legal value as I expect
an object of *any* other type to have a legal value. E.g. If I convert
a string into a DateTime object I'll expect that the object is in a
legal state after conversion or an exception being thrown otherwise.
And this is exactly what DateTime.Parse() does.
And they are introducing DateTime.TryParse() for just that reason, sometimes
an exception is just not acceptable.


An exception is only unacceptable, if you expect the
failed-calls/overall-calls ratio to be so high that performance may be
adversely affected. This also implies that you don't need to propagate
the error over many stack frames (if so then exceptions have a good
chance to outperform error-codes, not to mention the advantages of
exceptions concerning correctness). If a programmer uses TryParse in
such a situation then that's fine with me. However, I very much doubt
that (s)he could predict what that critical ratio is in the situation
at hand. I consider error-codes a fall-back that you only use when you
absolutely have to, i.e. when a profiler shows that exception
processing eats up significant amounts of the overall processor
cycles.
As for DateTime.TryParse(), yes I can imagine situations where you
really want to avoid that exception but are these situations so
common? I don't think so and neither does Microsoft as they would
otherwise have introduced TryParse() earlier. Note also that the
"default" function Parse() does throw exceptions.
Why should an int to enum conversion behave differently than a string
to DateTime conversion? In both cases the problem is the same: that an
object of the source type has many more legal states than an object of
the destination type.
it adds another point of failure to your application.


From what you have written so far, I assume that you would simply
allow the invalid enum value be processed and/or displayed by your
program. While I can imagine situations where it is perfectly
reasonable to do so (ignoring a problem and grinding on rather than
dealing with it), I don't think that this is good practice in most
real-world applications. The reasons are as follows:

- Most people prefer a program that refuses to perform an operation
when it detects a problem over a program that produces incorrect
results. This is/was the case in all projects I was involved in
- If you allow enums to have invalid values your *whole* program must
be able to deal with them, i.e. similar code must be spread
everywhere. I'd rather avoid this when I can make the checks once,
i.e. in the persistence or interfacing layer

It would depend on what the enums meaning was. If the enum specified an
operation, or a list entry, etc, then no I wouldn't. However, if it is just
an option and no option is as valid as all options, then yes I would. When I
load an enum, if the enum must have a value I do the checking. If it is
acceptable for it to be empty(granted, these are usually Flags decorated
enums), then I leave it be.


I would do exactly the same. Note that I'm not against means to make
unchecked enum conversions, it's just the default that I'm unhappy
with. I.e. I would like to see the cast throw exceptions but
Enum.ToObject and Enum.Parse can continue to work as they do today.
Most people will use the cast and so version problems, programmer
errors, etc. will surface very quickly.

[snip]
What is so complex about having to put a Flags attribute on an enum
that you don't want to have checked? Plus, either the compiler could
help you in many situations or you'd find out very soon when you test
your code for the first time. How this is implemented is of little
importance.


Its semantically wrong, IMHO, to use Flags on an enum that is not a flagged.
I'd argue for a Unchecked attribute before I'd accept using Flags on a
non-flagged enum.


That'd be perfectly fine with me. As I said, I only want *some* means
to implement strict enums. Moreover, I should be able to declare the
strict variant as default (see below).
> The checking would only be done for enums lacking the Flags attribute,
> enums with the Flags attribute would not be checked. This way the
> programmer has full control.

Which would result in ALOT of enums being marked as Flags(or an unstrict
attribute) because the programmer cannot allow member checking in his
situtation, either because they need an empty state in the enum or the enum value is generated outside of the runtime.


If you need an empty state, give the enum one. Period. I still fail to
see what the enum value being generated outside the runtime has to do
with invariant enforcement.


While thats preferable, it doesn't mean its always possible or it is always
done(not all enums in the world are under my control, for example)


Agreed. However, I think this is a rare case. Moreover, you can always
define your own enum with all necessary states and convert between the
two.

[snip]
This is such a common misconception. Why do you check the enum to
avoid the exception? As you can expect the exception to only be thrown
very rarely, the checking to avoid the exception will actually slow
the code down, because try blocks are a lot faster than ifs, as long
as no exception is thrown.


Because if I did not generate the enum value, there is NO reason to assume
the exception will be uncommon. If the enum is sourced by a non .NET
language or whatever, there is no way to assume it is correct.


We don't need to assume that it is correct, the only thing that
matters is whether it is *usually* correct or not (i.e. the
failed-calls/overall-calls ratio is low). Moreover, I have yet to see
a real-world program where bad-input detection is a performance issue
(I'd be very interested in an example). Bad input usually comes
directly from humans and I can't imagine a program where humans will
notice the difference in execution speed. Even if the input comes from
somewhere else e.g. the int in a DB then I'd say that the
*probability* to find a row with an incorrect value is normally really
low, even if the Db is filled by other programs written in other
languages. Moreover, as I mentioned earlier, finding such an incorrect
value often means that there is something seriously wrong that can
usually only be corrected by humans. In my current project (where I
have such a DB-int to enum conversion) I'd simply write an appropriate
log entry and then let the exception take the whole process down.
Whether that takes milliseconds or seconds is a non-issue.
Just as if
you were given a file name, do you jsut open the file and catch the
exception if it comes? or do you call File.Exists() to check while still
handling exceptions as they come.
It depends heavily on the context, IMHO. If you are dealing with ONE file,
then just relying on the exception is ok, if you are dealing with many, you
have no idea how common the issue will be and cannot rely on the exception
being rare. It could happen 500000 times, you cannot tell at runtime.
In most cases, I consider enums to be singlar operations, but then again, in
most cases I consider files to be singlar operations too. This change could
potentially seriously cut back on flexibility.
I'd always just try to open the file without checking because disk
operations tend to be orders of magnitude slower than anything that
can be done in the processor (including the throwing and catching of
an exception). This is also true for most other external sources (DB,
network, human, etc.)
Moreover, are you sure that there is a real-world application that
*usually* needs to try to open s..tloads of non-existent files?

[snip]
And I claim exactly the opposite, decent code never checks to avoid
exceptions that occur only rarely.
Moreover such errors (an enum having an invalid value) can almost
never be dealt with locally. More often than not the error has to be
passed up the call chain over several stack frames. This is exactly
what exceptions were invented for.

I agree, I just don't think the runtime should be throwing the exception. If
there is need for an exception to be thrown, I'll do it.


I'd could agree (although not fully) if this affected only relatively
experienced programmers in perfect project environments. However,
there are many many .NET newbies not knowing any better and most
projects get into more than one schedule-crunch where even the best
programmers become sloppy. In both cases people end up using casts. Of
course, the introduced bugs will surface eventually but determining
the cause is much more difficult then. Again, if a programmer made a
conscious decisition to use a non-throwing method then that's fine
with me. It's only the default I'm unhappy with.
Perhaps an Enum static method equivilent to the DateTime method ParseExact
would be more appropriate? While it wouldn't be called ParseExact,
obviously, as it doesn't deal with strings, but it seems like it would solve
this problem without an issue, allow casts to operate as is(breaking
existing functionality is also unattractive), and add a static member that
throws an exception if the enum value is incorrect, maybe something like
I agree that it's a bad idea to break with existing functionality.
However, this could also be implemented with a new compiler setting
(just like the one that determines whether to throw exceptions on
arithmetic under-/overflow).

[snip] The main advantage of this is it would allow both Flags and non-Flags
decorated enums to be validly converted in either situation. It can be that
in one case a Flags enum needs to be precise, but in others needs to be
loose. A specific rule using Flags potentially causes loss of flexibility.
Adding another attribute to the mix fixes that, but adds more complexity and
locks the enum's use to what the author of the enum wants. In some cases the
author cannot know how exactly the enum will be used outside of it being
Flags or a singular enum, or the enum will be of value in another situation.


Maybe, but this is rather uncommon isn't it? I tend to define new
enums for such cases.

Regards,

Andreas
Nov 15 '05 #19

P: n/a

"Andreas Huber" <ah****@gmx.net> wrote in message
news:3e**************************@posting.google.c om...
Daniel,
I fail to see what the underlying layout of a class or an enum has to
do with invariant enforcement. Just like a class an enum is simply an
abstract concept, nothing more nothing less.
I also don't to see why the source of an object (data base, file,
interlanguage call, etc.) should have an impact on whether the
invariants should be enforced or not.
When I save an enum into an external store and reload it later, I'll
just as much expect that the enum will have a legal value as I expect
an object of *any* other type to have a legal value. E.g. If I convert
a string into a DateTime object I'll expect that the object is in a
legal state after conversion or an exception being thrown otherwise.
And this is exactly what DateTime.Parse() does.
And they are introducing DateTime.TryParse() for just that reason, sometimes
an exception is just not acceptable.


An exception is only unacceptable, if you expect the
failed-calls/overall-calls ratio to be so high that performance may be
adversely affected. This also implies that you don't need to propagate
the error over many stack frames (if so then exceptions have a good
chance to outperform error-codes, not to mention the advantages of
exceptions concerning correctness). If a programmer uses TryParse in
such a situation then that's fine with me. However, I very much doubt
that (s)he could predict what that critical ratio is in the situation
at hand. I consider error-codes a fall-back that you only use when you
absolutely have to, i.e. when a profiler shows that exception
processing eats up significant amounts of the overall processor
cycles.
As for DateTime.TryParse(), yes I can imagine situations where you
really want to avoid that exception but are these situations so
common? I don't think so and neither does Microsoft as they would
otherwise have introduced TryParse() earlier. Note also that the
"default" function Parse() does throw exceptions.
Why should an int to enum conversion behave differently than a string
to DateTime conversion? In both cases the problem is the same: that an
object of the source type has many more legal states than an object of
the destination type.

> it adds another point of failure to your application.

From what you have written so far, I assume that you would simply
allow the invalid enum value be processed and/or displayed by your
program. While I can imagine situations where it is perfectly
reasonable to do so (ignoring a problem and grinding on rather than
dealing with it), I don't think that this is good practice in most
real-world applications. The reasons are as follows:

- Most people prefer a program that refuses to perform an operation
when it detects a problem over a program that produces incorrect
results. This is/was the case in all projects I was involved in
- If you allow enums to have invalid values your *whole* program must
be able to deal with them, i.e. similar code must be spread
everywhere. I'd rather avoid this when I can make the checks once,
i.e. in the persistence or interfacing layer

It would depend on what the enums meaning was. If the enum specified an
operation, or a list entry, etc, then no I wouldn't. However, if it is just
an option and no option is as valid as all options, then yes I would. When I load an enum, if the enum must have a value I do the checking. If it is
acceptable for it to be empty(granted, these are usually Flags decorated
enums), then I leave it be.


I would do exactly the same. Note that I'm not against means to make
unchecked enum conversions, it's just the default that I'm unhappy
with. I.e. I would like to see the cast throw exceptions but
Enum.ToObject and Enum.Parse can continue to work as they do today.
Most people will use the cast and so version problems, programmer
errors, etc. will surface very quickly.

[snip] What is so complex about having to put a Flags attribute on an enum
that you don't want to have checked? Plus, either the compiler could
help you in many situations or you'd find out very soon when you test
your code for the first time. How this is implemented is of little
importance.


Its semantically wrong, IMHO, to use Flags on an enum that is not a flagged.
I'd argue for a Unchecked attribute before I'd accept using Flags on a
non-flagged enum.


That'd be perfectly fine with me. As I said, I only want *some* means
to implement strict enums. Moreover, I should be able to declare the
strict variant as default (see below).
> The checking would only be done for enums lacking the Flags attribute, > > enums with the Flags attribute would not be checked. This way the
> > programmer has full control.
>
> Which would result in ALOT of enums being marked as Flags(or an unstrict > attribute) because the programmer cannot allow member checking in his > situtation, either because they need an empty state in the enum or
the
enum
> value is generated outside of the runtime.

If you need an empty state, give the enum one. Period. I still fail to
see what the enum value being generated outside the runtime has to do
with invariant enforcement.


While thats preferable, it doesn't mean its always possible or it is always done(not all enums in the world are under my control, for example)


Agreed. However, I think this is a rare case. Moreover, you can always
define your own enum with all necessary states and convert between the
two.

[snip] This is such a common misconception. Why do you check the enum to
avoid the exception? As you can expect the exception to only be thrown
very rarely, the checking to avoid the exception will actually slow
the code down, because try blocks are a lot faster than ifs, as long
as no exception is thrown.


Because if I did not generate the enum value, there is NO reason to assume
the exception will be uncommon. If the enum is sourced by a non .NET
language or whatever, there is no way to assume it is correct.


We don't need to assume that it is correct, the only thing that
matters is whether it is *usually* correct or not (i.e. the
failed-calls/overall-calls ratio is low). Moreover, I have yet to see
a real-world program where bad-input detection is a performance issue
(I'd be very interested in an example). Bad input usually comes
directly from humans and I can't imagine a program where humans will
notice the difference in execution speed. Even if the input comes from
somewhere else e.g. the int in a DB then I'd say that the
*probability* to find a row with an incorrect value is normally really
low, even if the Db is filled by other programs written in other
languages. Moreover, as I mentioned earlier, finding such an incorrect
value often means that there is something seriously wrong that can
usually only be corrected by humans. In my current project (where I
have such a DB-int to enum conversion) I'd simply write an appropriate
log entry and then let the exception take the whole process down.
Whether that takes milliseconds or seconds is a non-issue.


The best I can think of, a project I worked on about a year ago was
processing data files produced by a horridly buggy program(an apparently
rather old one which the company was unwilling to replace, even though it no
longer worked in their current situation). It would commonly pump out
invalid file names in the command file, or generate incorrect command
values. Of course, they didn't tell me this ahead of time, so I went ahead
and wrote against the (correct)test data they gave me, and when I went to
test it live, I found that the source could cause somewhere between 10% and
20% entries to be incorrect. So I was left with the task of making the
processor capable of handling all the possible invalid options, which meant
taking away exception handling in alot of cases where I could and using
manual checks, it wasn't acceptable to spend that much time processing
exceptions.
I don't know how often strange situations like that come up, I just know I
seem to find well more than my share of them.
Just as if
you were given a file name, do you jsut open the file and catch the
exception if it comes? or do you call File.Exists() to check while still
handling exceptions as they come.
It depends heavily on the context, IMHO. If you are dealing with ONE file, then just relying on the exception is ok, if you are dealing with many, you have no idea how common the issue will be and cannot rely on the exception being rare. It could happen 500000 times, you cannot tell at runtime.
In most cases, I consider enums to be singlar operations, but then again, in most cases I consider files to be singlar operations too. This change could potentially seriously cut back on flexibility.
I'd always just try to open the file without checking because disk
operations tend to be orders of magnitude slower than anything that
can be done in the processor (including the throwing and catching of
an exception). This is also true for most other external sources (DB,
network, human, etc.)
Moreover, are you sure that there is a real-world application that
*usually* needs to try to open s..tloads of non-existent files?


Well, the situation comes down in batch processing. If you have a list of
1000, 2000, 10000 files, the chances that 10 or 100 of them may not exist
isn't small, 10 or 100 exceptions isn't my kind of thing in that situation.
Also, the chances that the folder information is cached in memory is pretty
high, higher after the first call, assuming your not scanning across a huge
possible directory set. The call to File.Exists() should remove any disk
access required in the open call, otherwise the call to open the file would
take the same period of time.
Anyway, put enums in the same situation. Batch processing a huge collection
of basic entries, one member of which is a enum, if the exception from the
cast causes 1 second of delay, and there are many incorrect enums(that does
happen) what is the performance drain? This is a case where the value
matters, can be handled directly by the loader(just log a invalid entry and
move on). Granted a simple Try type method to load the enum and return false
if it fails would solve that problem as well.
[snip] And I claim exactly the opposite, decent code never checks to avoid
exceptions that occur only rarely.
Moreover such errors (an enum having an invalid value) can almost
never be dealt with locally. More often than not the error has to be
passed up the call chain over several stack frames. This is exactly
what exceptions were invented for.
I agree, I just don't think the runtime should be throwing the exception. If there is need for an exception to be thrown, I'll do it.


I'd could agree (although not fully) if this affected only relatively
experienced programmers in perfect project environments. However,
there are many many .NET newbies not knowing any better and most
projects get into more than one schedule-crunch where even the best
programmers become sloppy. In both cases people end up using casts. Of
course, the introduced bugs will surface eventually but determining
the cause is much more difficult then. Again, if a programmer made a
conscious decisition to use a non-throwing method then that's fine
with me. It's only the default I'm unhappy with.

Yeah, I can see where you are coming from, however there are a few issues.
For one, you still have to write verification code in your methods, because
enum isn't going to definatly be a correct value, as well as now it would be
a change of existing defaults, which as I've said, is an unpleasent thing. I
can't even be 100% sure my code won't collapse in the face of that change,
can you or anyone else? Currently, you would have to add try catch blocks to
every enum cast you do or risk an unexpected crash and burn.
Perhaps an Enum static method equivilent to the DateTime method ParseExact would be more appropriate? While it wouldn't be called ParseExact,
obviously, as it doesn't deal with strings, but it seems like it would solve this problem without an issue, allow casts to operate as is(breaking
existing functionality is also unattractive), and add a static member that throws an exception if the enum value is incorrect, maybe something like
I agree that it's a bad idea to break with existing functionality.
However, this could also be implemented with a new compiler setting
(just like the one that determines whether to throw exceptions on
arithmetic under-/overflow).

Still, that generates unexpected functionality to the experianced developer
if set on by default, and would be ignored by the new programmer if it was
set off. [snip]
The main advantage of this is it would allow both Flags and non-Flags
decorated enums to be validly converted in either situation. It can be that in one case a Flags enum needs to be precise, but in others needs to be
loose. A specific rule using Flags potentially causes loss of flexibility. Adding another attribute to the mix fixes that, but adds more complexity and locks the enum's use to what the author of the enum wants. In some cases the author cannot know how exactly the enum will be used outside of it being
Flags or a singular enum, or the enum will be of value in another
situation.
Maybe, but this is rather uncommon isn't it? I tend to define new
enums for such cases. It depends, for some things, replacing system enums is a bad idea, as it
seems to confuse people. I don't see any reason why there needs to be four
identical WindowState enums or whatever. For a third party library I'll
rarely reuse one, but I don't like the confusion included with providing an
identical, both by contents and its semantic usage, replacement to something
defined in the mscorlib or System assemblies. Beyond that, you can't always
ignore the uncommon, it seems they come up more commonly across the board
than it ever seems they could.
Regards,

Andreas

Nov 15 '05 #20

P: n/a
Daniel,
Because if I did not generate the enum value, there is NO reason to assume the exception will be uncommon. If the enum is sourced by a non .NET
language or whatever, there is no way to assume it is correct.
We don't need to assume that it is correct, the only thing that
matters is whether it is *usually* correct or not (i.e. the
failed-calls/overall-calls ratio is low). Moreover, I have yet to see
a real-world program where bad-input detection is a performance issue
(I'd be very interested in an example). Bad input usually comes
directly from humans and I can't imagine a program where humans will
notice the difference in execution speed. Even if the input comes from
somewhere else e.g. the int in a DB then I'd say that the
*probability* to find a row with an incorrect value is normally really
low, even if the Db is filled by other programs written in other
languages. Moreover, as I mentioned earlier, finding such an incorrect
value often means that there is something seriously wrong that can
usually only be corrected by humans. In my current project (where I
have such a DB-int to enum conversion) I'd simply write an appropriate
log entry and then let the exception take the whole process down.
Whether that takes milliseconds or seconds is a non-issue.


The best I can think of, a project I worked on about a year ago was
processing data files produced by a horridly buggy program(an apparently
rather old one which the company was unwilling to replace, even though it no
longer worked in their current situation). It would commonly pump out
invalid file names in the command file, or generate incorrect command
values. Of course, they didn't tell me this ahead of time, so I went ahead
and wrote against the (correct)test data they gave me, and when I went to
test it live, I found that the source could cause somewhere between 10% and
20% entries to be incorrect. So I was left with the task of making the
processor capable of handling all the possible invalid options, which meant
taking away exception handling in alot of cases where I could and using
manual checks, it wasn't acceptable to spend that much time processing
exceptions.
I don't know how often strange situations like that come up, I just know I
seem to find well more than my share of them.


How can a program obviously doing lots of disk I/O be slowed down
noticeably by something that happens entirely in the processor? Yes
the processing of one exception is slow when directly compared to a
single if but I can't really believe it is so slow that it overshadows
the time spent reading a single file. More specifically, you say that
about 20% of the files were non-existent, how can the time spent
processing the exceptions thrown for those 20% be in the same league
as the time spent reading/writing the existing 80% of the files?
In my experience the processing of a single exception takes
microseconds (I've just tested it) whereas I/O is always in the
millisecond range. The only thing that takes a lot of time is when you
query the stack trace of an exception, that is usually in the second
range.
BTW, I don't doubt your experience it is just so contrary to
everything I've seen.
Do you have any before/after timings of your app, if possible with
stats that show how many exceptions were thrown?
I'd always just try to open the file without checking because disk
operations tend to be orders of magnitude slower than anything that
can be done in the processor (including the throwing and catching of
an exception). This is also true for most other external sources (DB,
network, human, etc.)
Moreover, are you sure that there is a real-world application that
*usually* needs to try to open s..tloads of non-existent files?


Well, the situation comes down in batch processing. If you have a list of
1000, 2000, 10000 files, the chances that 10 or 100 of them may not exist
isn't small, 10 or 100 exceptions isn't my kind of thing in that situation.
Also, the chances that the folder information is cached in memory is pretty
high, higher after the first call, assuming your not scanning across a huge
possible directory set. The call to File.Exists() should remove any disk
access required in the open call, otherwise the call to open the file would
take the same period of time.


Again, I assume you are going to read/write the files that you have
opened successfully. No matter how small amounts of data you
read/write from/to each file it's always going to take milliseconds as
there is no way that their content is already cached, unless you run
your batch processing app twice on the same data what sort of defeats
the whole purpose of batch processing, doesn't it?
Moreover, the processing of those 100 exceptions will only take
milliseconds. How should that ever be noticeable?
Anyway, put enums in the same situation. Batch processing a huge collection
of basic entries, one member of which is a enum, if the exception from the
cast causes 1 second of delay, and there are many incorrect enums(that does
happen) what is the performance drain? This is a case where the value
matters, can be handled directly by the loader(just log a invalid entry and
move on). Granted a simple Try type method to load the enum and return false
if it fails would solve that problem as well.
I don't see how the difference between the processing of one exception
and the processing of one error-code can be anywhere near one second.
This can only happen if you query the stack trace of the exception but
that would not be fair as you don't have a stack-trace with
error-codes, right?

BTW, one other situation where exception processing is really slow is
when you run a program in the debugger, but I guess that was not the
case when you took those timings.

[snip]
I agree that it's a bad idea to break with existing functionality.
However, this could also be implemented with a new compiler setting
(just like the one that determines whether to throw exceptions on
arithmetic under-/overflow).

Still, that generates unexpected functionality to the experianced developer
if set on by default, and would be ignored by the new programmer if it was
set off.


Not quite, you forget the situation where you have one project
architect setting up the VS project, working together with a number of
newbies. This is the most common situation in projects today.
I would therefore be happy when the setting is off by default, I can
then turn it on for new projects and leave it off for current
projects.
[snip]
The main advantage of this is it would allow both Flags and non-Flags
decorated enums to be validly converted in either situation. It can be that in one case a Flags enum needs to be precise, but in others needs to be
loose. A specific rule using Flags potentially causes loss of flexibility. Adding another attribute to the mix fixes that, but adds more complexity and locks the enum's use to what the author of the enum wants. In some cases the author cannot know how exactly the enum will be used outside of it being
Flags or a singular enum, or the enum will be of value in another

situation.

Maybe, but this is rather uncommon isn't it? I tend to define new
enums for such cases.

It depends, for some things, replacing system enums is a bad idea, as it
seems to confuse people. I don't see any reason why there needs to be four
identical WindowState enums or whatever.


I meant that you only create a new enum if an existing one nearly but
not quite fits your needs. I never felt that urge for enums provided
by the framework.
For a third party library I'll
rarely reuse one, but I don't like the confusion included with providing an
identical, both by contents and its semantic usage, replacement to something
defined in the mscorlib or System assemblies.
If you really want to create enum objects having more states than what
the enum definition in the .NET framework allows then you're doing
something that is rather uncommon. You could still do it but you'd
have to take the detour via a special function rather than the direct
route via the cast. I think that's perfectly reasonable.
Beyond that, you can't always
ignore the uncommon, it seems they come up more commonly across the board
than it ever seems they could.


As I've said several times now: I don't want to ignore the uncommon!
Rather, I want the uncommon to be more complicated (or less obvious)
than the common. With the current implementation of enums it is
exactly the other way round, which is a burden for I guess at least
90% of the users.

Regards,

Andreas
Nov 15 '05 #21

P: n/a

"Andreas Huber" <ah****@gmx.net> wrote in message
news:3e**************************@posting.google.c om...
Daniel,
How can a program obviously doing lots of disk I/O be slowed down
noticeably by something that happens entirely in the processor? Yes
the processing of one exception is slow when directly compared to a
single if but I can't really believe it is so slow that it overshadows
the time spent reading a single file. More specifically, you say that
about 20% of the files were non-existent, how can the time spent
processing the exceptions thrown for those 20% be in the same league
as the time spent reading/writing the existing 80% of the files?
In my experience the processing of a single exception takes
microseconds (I've just tested it) whereas I/O is always in the
millisecond range. The only thing that takes a lot of time is when you
query the stack trace of an exception, that is usually in the second
range.
BTW, I don't doubt your experience it is just so contrary to
everything I've seen.
Do you have any before/after timings of your app, if possible with
stats that show how many exceptions were thrown?

It wasn't significant, however when it slowed down the response time the
users wanted they got upset, as with many things, perception matttered more
than reality. Often times it'd have large blocks of corrupt files in a row,
and the company got upset if they didn't see files changing. Thinking about
it now, if I had just displayed the next file name after each exception and
moved on there would have been no problem, however in that harried and
annoyed state I was in fixing the problem that particular solution didn't
come to me(never said I was a very good UI designer). I didn't keep any
timings, but the speed difference wasn't significant, the UI just didn't
stop for a few seconds at a time per batch(of course, most exceptions were
logged...don't recall if I was calling the log method for file exceptions or
not). If I was that would have certainly be a very nasty perf problem as
well, 20,000 or so stack trace queries in a row...performance wasn't that
bad.
As I said, it wasn't a very good example, sadly embaressing example, but it
was the best I could think of.
I'd always just try to open the file without checking because disk
operations tend to be orders of magnitude slower than anything that
can be done in the processor (including the throwing and catching of
an exception). This is also true for most other external sources (DB,
network, human, etc.)
Moreover, are you sure that there is a real-world application that
*usually* needs to try to open s..tloads of non-existent files?


Well, the situation comes down in batch processing. If you have a list of
1000, 2000, 10000 files, the chances that 10 or 100 of them may not exist isn't small, 10 or 100 exceptions isn't my kind of thing in that situation. Also, the chances that the folder information is cached in memory is pretty high, higher after the first call, assuming your not scanning across a huge possible directory set. The call to File.Exists() should remove any disk
access required in the open call, otherwise the call to open the file would take the same period of time.


Again, I assume you are going to read/write the files that you have
opened successfully. No matter how small amounts of data you
read/write from/to each file it's always going to take milliseconds as
there is no way that their content is already cached, unless you run
your batch processing app twice on the same data what sort of defeats
the whole purpose of batch processing, doesn't it?
Moreover, the processing of those 100 exceptions will only take
milliseconds. How should that ever be noticeable?
Anyway, put enums in the same situation. Batch processing a huge collection of basic entries, one member of which is a enum, if the exception from the cast causes 1 second of delay, and there are many incorrect enums(that does happen) what is the performance drain? This is a case where the value
matters, can be handled directly by the loader(just log a invalid entry and move on). Granted a simple Try type method to load the enum and return false if it fails would solve that problem as well.


I don't see how the difference between the processing of one exception
and the processing of one error-code can be anywhere near one second.
This can only happen if you query the stack trace of the exception but
that would not be fair as you don't have a stack-trace with
error-codes, right?

BTW, one other situation where exception processing is really slow is
when you run a program in the debugger, but I guess that was not the
case when you took those timings.

[snip] I agree that it's a bad idea to break with existing functionality.
However, this could also be implemented with a new compiler setting
(just like the one that determines whether to throw exceptions on
arithmetic under-/overflow).

Still, that generates unexpected functionality to the experianced developer
if set on by default, and would be ignored by the new programmer if it was set off.


Not quite, you forget the situation where you have one project
architect setting up the VS project, working together with a number of
newbies. This is the most common situation in projects today.
I would therefore be happy when the setting is off by default, I can
then turn it on for new projects and leave it off for current
projects.
[snip]
> The main advantage of this is it would allow both Flags and non-Flags > decorated enums to be validly converted in either situation. It can be
that
> in one case a Flags enum needs to be precise, but in others needs to
be > loose. A specific rule using Flags potentially causes loss of

flexibility.
> Adding another attribute to the mix fixes that, but adds more complexity and
> locks the enum's use to what the author of the enum wants. In some
cases the
> author cannot know how exactly the enum will be used outside of it
being > Flags or a singular enum, or the enum will be of value in another

situation.

Maybe, but this is rather uncommon isn't it? I tend to define new
enums for such cases.

It depends, for some things, replacing system enums is a bad idea, as it
seems to confuse people. I don't see any reason why there needs to be

four identical WindowState enums or whatever.


I meant that you only create a new enum if an existing one nearly but
not quite fits your needs. I never felt that urge for enums provided
by the framework.
For a third party library I'll
rarely reuse one, but I don't like the confusion included with providing an identical, both by contents and its semantic usage, replacement to something defined in the mscorlib or System assemblies.


If you really want to create enum objects having more states than what
the enum definition in the .NET framework allows then you're doing
something that is rather uncommon. You could still do it but you'd
have to take the detour via a special function rather than the direct
route via the cast. I think that's perfectly reasonable.
Beyond that, you can't always
ignore the uncommon, it seems they come up more commonly across the board than it ever seems they could.


As I've said several times now: I don't want to ignore the uncommon!
Rather, I want the uncommon to be more complicated (or less obvious)
than the common. With the current implementation of enums it is
exactly the other way round, which is a burden for I guess at least
90% of the users.

Regards,

Andreas

Nov 15 '05 #22

This discussion thread is closed

Replies have been disabled for this discussion.