|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Announcements
Chapters
Services
Feature Zones
|
IntroductionThis article presents yet another C# set class, namely The actual operations are done by converting/typecasting the passed in object parameters to integers and then applying bit-wise operations. I'm coming from Borland Delphi to C# and I'm just a C# and .NET novice. Delphi provides a set type and I miss that in C#. So I decided to code one. Well, there is already a C# set class in CodeProject, described in the article "A C# sets class" by Richard Bothne and Jim Showalter, but that Sets explainedA set type is a data type which defines a collection of values of the same base type. C# does not provide a set type but we can simulate set variables. enum Day { Saturday, Sunday, Monday, Tuesday, Wednesday,
Thursday, Friday }; // a "base type"
....
Day WeekEnd = Day.Saturday| Day.Sunday; // a "set"
Day WorkDays = Day.Monday | Day.Tuesday | Day.Wednesday
| Day.Thursday | Day.Friday ; // a "set"
It is not meaningful for a value to be included twice in a set, although it is not an error if you do that. There are some operations we can apply to sets:
Sets are useful in solving many programming problems, and they promote code clarity and readability. Not all languages provide a set type. In those cases, one could use carefully assigned integer constants and then apply bitwise operations on them. Bit-wise operations are not an un-common method in C/C++ and Win32 programming. const int cLeft = 1;
const int cUp = 2;
const int cRight = 4;
const int cDown = 8;
...
int Directions = cRight | cDown; // Union
if ((cRight & Directions) == cRight)
// Membership - is cRight included in Directions?
MessageBox.Show("Going right");
.NET FlagsAttribute class and setsAt the Based on the above, the following should not be legal: enum Day { Saturday, Sunday, Monday, Tuesday, Wednesday, Thursday, Friday };
....
Day A = Day.Friday | Day.Tuesday;
Well, legal or not, it compiles fine. More one that, one reading the documentation regarding the I believe Anyway, if you assign those values to your constants the way I described, then you can use OR-ing, AND-ing and XOR-ing against them. And it seems, we get corrects results even if we omit the // if you un-comment the attribute the only difference
// is that the first message box displays
// the string value, that is the day names of the set,
// else you get its numeric value
//[FlagsAttribute]
enum Day { Saturday = 1, Sunday = 2, Monday = 4, Tuesday = 8,
Wednesday = 16, Thursday = 32, Friday = 64 };
...
Day A = Day.Saturday | Day.Friday | Day.Sunday;
Day B = Day.Sunday;
MessageBox.Show(A.ToString());
bool b = (((int)B & (int)A) == (int)B); // ugly eh? isn't it?
MessageBox.Show(b.ToString());
Of course, to get the most, just apply the Simulating setsNow the rest is easy. In order to simulate sets, we just convert those // Union
(int)A | (int)B
// Intersection
(int)A & (int)B
// Difference
(int)((int)A | (int)B) ^ (int)B
// Membership
(((int)A & (int)B) == (int)A)
We can code a function for each of the above operations. if ((A == null) || (B == null))
throw(new ArgumentNullException());
if (A.GetType() != B.GetType())
throw(new Exception("Different set types"));
The CSet classSo, now we can have the full class coded using the above. Our public class CSet: object
{
// Union
public static object Or(object A, object B)
{
if ((A == null) || (B == null)) throw(new ArgumentNullException());
if (A.GetType() != B.GetType()) throw(new Exception("Different set types"));
return (int)A | (int)B;
}
public static object Union(object A, object B)
{
if ((A == null) || (B == null)) throw(new ArgumentNullException());
if (A.GetType() != B.GetType()) throw(new Exception("Different set types"));
return (int)A | (int)B;
}
// Intersection
public static object And(object A, object B)
{
if ((A == null) || (B == null)) throw(new ArgumentNullException());
if (A.GetType() != B.GetType()) throw(new Exception("Different set types"));
return (int)A & (int)B;
}
public static object Intersection(object A, object B)
{
if ((A == null) || (B == null)) throw(new ArgumentNullException());
if (A.GetType() != B.GetType()) throw(new Exception("Different set types"));
return (int)A & (int)B;
}
// Difference
public static object Xor(object A, object B)
{
if ((A == null) || (B == null)) throw(new ArgumentNullException());
if (A.GetType() != B.GetType()) throw(new Exception("Different set types"));
return (int)((int)A | (int)B) ^ (int)B;
}
public static object Diff(object A, object B)
{
if ((A == null) || (B == null)) throw(new ArgumentNullException());
if (A.GetType() != B.GetType()) throw(new Exception("Different set types"));
return (int)((int)A | (int)B) ^ (int)B;
}
// Membership - A in B, A can be a single value or a set.
public static bool In(object A, object B)
{
if ((A == null) || (B == null)) throw(new ArgumentNullException());
if (A.GetType() != B.GetType()) throw(new Exception("Different set types"));
return (((int)A & (int)B) == (int)A);
}
}
Using the codeTo use the code, copy the class into a source document, choosing an appropriate namespace and then... //[FlagsAttribute]
//enum Day { Saturday, Sunday, Monday, Tuesday, Wednesday, Thursday, Friday };
[FlagsAttribute]
enum Day { Saturday = 1, Sunday = 2, Monday = 4, Tuesday = 8,
Wednesday = 16, Thursday = 32, Friday = 64 };
private void button1_Click(object sender, System.EventArgs e)
{
// Union
Day A = Day.Wednesday;
Day B = Day.Friday | Day.Tuesday; // OR using |
Day C = (Day)CSet.Or(A, B); // OR using CSet.Or()
MessageBox.Show(C.ToString());
// Intersection
C = (Day)CSet.And(Day.Tuesday, B);
MessageBox.Show(C.ToString());
// Difference
A = Day.Wednesday;
B = Day.Wednesday | Day.Wednesday;
C = (Day)CSet.Xor(A, B);
MessageBox.Show(C.ToString());
// Membership
A = Day.Wednesday | Day.Tuesday;
B = Day.Wednesday;
MessageBox.Show(CSet.In(B, A).ToString());
}
That's it. I hope you'll find this tiny class useful.
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||