|
|
Comments and Discussions
|
|
 |

|
Smart K8 wrote: I've just stripped away all the code non-concerned in the article
And didn't test it?
I meant, in the line:
public static bool IsChild<ttype>(TType child, TType parent)
where is ttype used? Is it supposed to be TType and you didn't capitalize it properly?
Smart K8 wrote: There's no constraint for Enum
Yeah, and there should be. Stupid Microsoft
Anyway, I spent another whole day today tweaking my implementation of this.
|
|
|
|

|
PIEBALDconsult wrote: Smart K8 wrote:
I've just stripped away all the code non-concerned in the article
And didn't test it?
Sure I did.
PIEBALDconsult wrote:
I meant, in the line:
public static bool IsChild(TType child, TType parent)
where is ttype used? Is it supposed to be TType and you didn't capitalize it properly?
No, I'm just struggling with the codeproject's < and > a bit.
The wisdom is to see things truthfully.
|
|
|
|

|
Why did you choose to shift the higher-order sub-values up?
I would leave them in place (at the high-end), leave low-order fields as 0 to indicate "class", and add (OR) detail as I go.
The "class" parts could also be at the low-end, but I think high-end is clearer.
(Hexadecimal literals would make it easier too. They following doesn't work correctly, but should give a decent conceptual view.)
public enum AnimalKind
{
Unknown = 00000,
Class = 90000,
Subclass = 90900,
DomesticAnimals = 10000,
Dog = 10100,
Dalmatin = 10101,
Greyhound = 10102,
Malamute = 10103,
Terrier = 10104,
Cat = 10200,
WildAnimals = 20000,
Ape = WildAnimals + 100,
Chimpanzee = 20101,
Gorilla = 20102,
Orangutan = 20103,
Deer = WildAnimals + 200
}
That way bitwise operations can be used (I hope I get this right):
if ( ( AnimalKind.Greyhound & AnimalKind.Subclass ) == AnimalKind.Dog )
|
|
|
|

|
This is what I mean:
namespace Template
{
public partial class Template
{
public enum AnimalKind
{
Unknown = 0x000000,
Class = 0xFF0000,
Subclass = 0xFFFF00,
DomesticAnimals = 0x010000,
Dog = 0x010100,
Dalmatin = 0x010101,
Greyhound = 0x010102,
Malamute = 0x010103,
Terrier = 0x010104,
Cat = 0x010200,
WildAnimals = 0x020000,
Ape = WildAnimals | 0x0100,
Chimpanzee = Ape | 0x01,
Gorilla = Ape | 0x02,
Orangutan = Ape | 0x03,
Deer = WildAnimals | 0x0200
}
public static void
Main
(
string[] args
)
{
AnimalKind a = AnimalKind.Unknown ;
if ( ( args.Length > 0 ) && System.Enum.IsDefined ( typeof(AnimalKind) , args [ 0 ] ) )
{
a = (AnimalKind) System.Enum.Parse ( typeof(AnimalKind) , args [ 0 ] ) ;
}
System.Console.WriteLine
(
"{0} {1:X06} {2} {3}"
,
a
,
(int) a
,
a & AnimalKind.Class
,
a & AnimalKind.Subclass
) ;
switch ( a & AnimalKind.Subclass )
{
case AnimalKind.Dog :
System.Console.WriteLine ( "Arf" ) ;
break ;
case AnimalKind.Cat :
System.Console.WriteLine ( "Meow" ) ;
break ;
}
}
}
}
|
|
|
|

|
Hi.. What you are describing is simple the [Flags] attribute.
The point is in the combination of scalability (branch count/level count) and the ability to list all the children because of that simple fact. Consider this question:
How do you construct a tree with three (or more) levels (A->AB->ABC) and then reconstruct it again to List<TEnumType> GetList<TEnumType>(TEnumType Parent) ?
// Why did you choose to shift the higher-order sub-values up?
Because of the scalability. It seems more natural that a tree starts small. Check this rephrase:
[Structured(100)]
public enum AnimalKind
{
Unknown = 00000,
DomesticAnimals = 1,
Dog = 100,
Dalmatin = 10000,
Greyhound = 10001,
Malamute = 10002,
Terrier = 10003,
Cat = 101,
WildAnimals = 2,
Ape = 200,
Chimpanzee = 20000,
Gorrila = 20001,
Orangutan = 20002,
Deer = 201
}
Do you see the logic now ?
regards,
Kate
The wisdom is to see things truthfully.
The wisdom is to see things truthfully.
|
|
|
|

|
Smart K8 wrote: What you are describing is simple the [Flags] attribute.
Not at all.
Smart K8 wrote: Do you see the logic now ?
Just as I saw it before, but I don't agree that it's the best course of action.
|
|
|
|

|
Sorry, I got confused with another thread.. I guess I'm getting tired.. It's 23:37 here. I'm going to sleep. I checked your solution and this is ofcourse possible but consider the scenario where the Span (as I call it) won't be 0xFF but something lower than that (for example 0xC) because the complexity of the tree won't be sufficient to hold the number anymore.
Class = 0xFF000000,
Subclass = 0xFFFF0000,
SubSubClass = 0xFFFFFF00,
SubSubSubClass = 0xFFFFFFFF,
SubSubSubSubClass = Hello problems!
That's where the (for example) [Structured(0xC)] takes control and also when Natural numbers looks a bit more normal.
regards,
Kate
The wisdom is to see things truthfully.
|
|
|
|

|
Smart K8 wrote: consider the scenario where the Span...
I was simply following your lead of using two digits. But what if you want different spans at different levels? For instance one-digit at the top-most level and two-digits at the next level down?
And, no, I haven't worked that out yet either, but I expect yout Attribute-based solution will be the way to go.
I also acknowledge that you were after a solution that wasn't tied to a particular enum. We'll get there, baby steps.
Smart K8 wrote: Natural numbers looks a bit more normal
You're saying my numbers are unnatural?
Well, the great whole purpose of enums is to hide the actual values anyway.
|
|
|
|

|
You're saying my numbers are unnatural?
IMHO.. in the end it is not important if you choose decimals, hexadecimals or any other representation of the value. I guess it's up to reader to make it suitable. I just thought that using decimals numbers as an example will be understable to a more general public.
And, no, I haven't worked that out yet either, but I expect yout Attribute-based solution will be the way to go.
I also acknowledge that you were after a solution that wasn't tied to a particular enum.
Exactly, prior to posting the article (or even thinking about the solution itself) I was considering all the ways possible to achieve that with either standard enumerations or any other easy way. It was expected that the consensus that this solution is not reinventing the wheel (as leppie pointed out) is first to be made.
The Structured attribute is there only to normalize all the possible granulations of enumerations so then one method can be used to reconstruct the tree + some value is ofcourse in the methods themselves.
We'll get there, baby steps.
Sure and the reasonable compromise of syntax is what I'm after too. I'm glad for every suggestion and I guess I'm willing to modify the article when the best solution is worked out.
regards,
Kate
The wisdom is to see things truthfully.
modified on Sunday, April 6, 2008 3:23 AM
|
|
|
|

|
And thinking bit-wise allows more granularity of the class sizes. Yours only allows 10, 100, 1000, etc. members per class; but mine allows 3, 7, 15, 31, etc.
|
|
|
|

|
What you are looking for is bit masks, and that is built into enum in C# (and many other languages) already.
[edit] you article is by no means bad [edit]
|
|
|
|

|
Hi, I'm aware of the FlagsAttribute but if you give it another round I hope you'll notice the slight improvements which are important in this case.
regards,
Kate
|
|
|
|

|
Sorry I dont see it You can do the same with enums. You dont even need the Flags attribute. Here is a number hierarchy:
<font color="Blue">enum</font> <font color="Teal">NumberClass</font>
<font color="DarkBlue">{</font>
Complex <font color="DarkBlue">=</font> <font color="Red">1</font><font color="DarkBlue">,</font>
Real <font color="DarkBlue">=</font> <font color="Red">2</font> <font color="DarkBlue">|</font> Complex<font color="DarkBlue">,</font>
Rational <font color="DarkBlue">=</font> <font color="Red">4</font> <font color="DarkBlue">|</font> Real <font color="DarkBlue">,</font>
BigInteger <font color="DarkBlue">=</font> <font color="Red">8</font> <font color="DarkBlue">|</font> Rational<font color="DarkBlue">,</font>
Integer <font color="DarkBlue">=</font> <font color="Red">16</font> <font color="DarkBlue">|</font> BigInteger<font color="DarkBlue">,</font>
NotANumber <font color="DarkBlue">=</font> <font color="Red">0</font>
<font color="DarkBlue">}</font>
|
|
|
|

|
Ok.. So how about a second branch in the same enum ?
regards,
Kate
The wisdom is to see things truthfully.
|
|
|
|

|
enum
{
Unknown = 0,
Dalmatin = 1,
Greyhound = 2,
Malamute = 3,
Terrier = 4,
DogMask = 0x0F,
CatMask = 0xF0, DomesticMask = 0xFF,
Chimp = 0x0100,
Gorilla = 0x0200,
Orange = 0x0400 ApeMask = 0x0F00,
DeerMask = 0xF000,
WildAnimalMask = 0xFF00,
};
There are some advantages inyour solution, but for me not enough to warrant the unusual solution. It's pretty limited anyway (whether you use binary masking or some decimal grouping), binary is much more common and thus preferable in my book.
We are a big screwed up dysfunctional psychotic happy family - some more screwed up, others more happy, but everybody's psychotic joint venture definition of CP blog: TDD - the Aha! | Linkify!| FoldWithUs! | sighist
|
|
|
|

|
Now we're getting somewhere..
DogMask = 0x0F, CatMask = 0xF0,
This example - as you pointed out in comments - uses a span (or granularity.. used by PIEBALDconsult) of 16 thus allowing room for 15 items. Sure if you need to make another enumeration and you want to have more than 16 items you'll make span wider for example.
FieldPlants = 0x00FF, GardenPlants = 0xFF00,
Now try to use ONE method to reconstruct the tree for both enumerations. Not possible ?
Whether you'll choose hexadecimals over decimals or high-ordering over low-ordering is not a concern of this article as much. Rather it is a normalized way to reconstruct a tree from the enumerations with different granularities.
regards,
Kate
The wisdom is to see things truthfully.
|
|
|
|

|
Ok, I took some time and tried your proposed solution the result tree for parent (DogMask) is as follows..
DogMask
Dalmatin
Greyhound
Malamute
Dalmatin (?)
Greyhound (?)
Terrier
and the correct result should be
DogMask
Dalmatin
Greyhound
Malamute
Terrier
Also another enumeration reconstructed tree:
WildAnimalMask
Chimp
Gorilla
Orange
ApeMask
Chimp
Gorilla
Orange
DeerMask
and again the correct result should be:
WildAnimalMask
ApeMask
DeerMask
So tell me what is going on here, how do you propose to reconstruct a TREE for a particular enumeration value from your suggested enumeration ?
regards,
Kate
The wisdom is to see things truthfully.
|
|
|
|

|
Smart K8 wrote: Whether you'll choose hexadecimals over decimals or high-ordering over low-ordering is not a concern of this article as much. Rather it is a normalized way to reconstruct a tree from the enumerations with different granularities.
Yes, but it should also be fairly efficient and maintainable, and I suspect that having the class (or whatever) value shift around is the opposite of that.
Smart K8 wrote: Now try to use ONE method to reconstruct the tree for both enumerations.
Now that it's the weekend I have more time to think about this. So what form should the tree take?
I guess before we address that; what functions should be available?
|
|
|
|

|
PIEBALDconsult wrote: Smart K8 wrote:
Whether you'll choose hexadecimals over decimals or high-ordering over low-ordering is not a concern of this article as much. Rather it is a normalized way to reconstruct a tree from the enumerations with different granularities.
Yes, but it should also be fairly efficient and maintainable, and I suspect that having the class (or whatever) value shift around is the opposite of that.
You surely are right on the point of efficiency and maintainability. I was just answering to leppie who didn't get that this idea is not a reinventing the wheel and it is not possible to structure the tree using the bitwise masks this will only get you all the parents but not an immediate one.
Smart K8 wrote:
Now try to use ONE method to reconstruct the tree for both enumerations.
Now that it's the weekend I have more time to think about this. So what form should the tree take?
I guess before we address that; what functions should be available?
Basically you should have the EnumType.IsChild(EnumType parent) which will detect if a specified enumeration value is a child of a specific direct parent (I'll try to elaborate on the Extension methods in C# if there is a way to extend the enumerations via System.Enum but I guess it is not possible). The listing method is only the cream on the top of it. With the IsChild (or an alternative method) you should be able to reconstruct a tree (either visual one or non-visual one). That's the main point of the article. If there's better way of achieving that with enumerations in different hierarchy style (either low-ordering) it will be an improvement (and I'll be happy to hear about it).
regards,
Kate
The wisdom is to see things truthfully.
|
|
|
|

|
Mask! Yeah, that was the term I needed!
|
|
|
|

|
leppie wrote: [edit] you article is by no means bad [edit]
I just wanted to second this. It's an interesting concept; it just needs a cleaner implementation.
|
|
|
|
 |
|
|
General News Suggestion Question Bug Answer Joke Rant Admin
|
The way to maintain a tree structured enumeration while having all the advantages of the standard ones
| Type | Article |
| Licence | CPOL |
| First Posted | 2 Apr 2008 |
| Views | 32,259 |
| Downloads | 114 |
| Bookmarked | 13 times |
|
|