Reputation: 6147
In my scenario I have a class called Person. I need to test if certain people are compatible or not and return a bool value. I was thinking of using an enum setup to make it easier to test these compatibility tests. However I'm not familiar with enum and was hoping someone could shed some light or help demonstrate how i would use it in my case.
I was thinking it would be easiest to assign an id to each Person and a compatibility list along with that ID. Below is some pseudo code demonstrating what i mean. I'm just not clear on how to to set this up using enums.
ID's assigned to each class object
1 = Person(John)
2 = Person(Kevin)
3 = Person(Michelle)
4 = Person(Krystal)
5 = Person(Leslie)
Compatibility lists
1 = [2,4]
2 = [1,3,5]
3 = [2,5]
4 = [1]
5 = [2,3]
The tests I want to Perform and return a bool value.
If (Person(John) compatible with Person(Krystal))
{return true}else{return false}
Upvotes: 0
Views: 240
Reputation: 39277
Honestly, an enum
is not the solution for this. The closest analogy to your "compatibility checker" would probably be an EqualityComparer<T>
in .NET. It's a separate class.
The comparison "are two people compatible" really doesn't belong in the Person class. It depends on what measure of compatibility you are comparing them and over time that comparison may change or you may add other compatibility comparers.
So, instead of an enum
create a CompatibilityComparer
class. For now this has one method .IsCompatible(Person a, Person b)
and inside that method you can use a dictionary, database lookup, complex calculation based on weighted values from a and b, or whatever else you want.
private static readonly CompatibilityComparer comparer
= new CompatibilityComparer();
...
if (comparer.IsCompatible(john, krystal)) ...
See separation of concerns and single responsibility principle.
Ideally your comparer would also operate on an interface IPerson
rather than the concrete class Person
so you can test it more easily with mock IPerson
objects.
A simplest example, using a Dictionary of compatible people might be:
Dictionary<int, int[]> matrix = new Dictionary<int, int[]>();
// You could initialize this statically, or better yet, use Lazy<>
static CompatibilityComparer()
{
matrix[1] = new[] { 2, 4 };
...
}
public bool IsCompatible(Person a, Person b)
{
return matrix[a.Id].Contains(b.Id);
}
You could also represent your graph of compatibility as a list of pairs of compatible people ids, as a 2D square matrix, or any other graph representation.
If you really do have all the Person
objects in memory, statically defined, it would be better to have a Dictionary<Person, List<Person>>
although at some point one has to ask, "what's the real environment here?", it's not an interesting problem until there are thousands of People and they are in a database and then a different approach is needed again.
How was 'compatibility' decided? a) by a person entering data in a database or b) by some algorithm? If the former then that would involve Ids and a 'compatibility' table in the database with two foreign keys back to the people table (like the dictionary is meant to illustrate). And if the latter why isn't that in code?
Upvotes: 4
Reputation: 571
What you want is an enum type with the flags attribute:
[Flags]
enum MyCompatibilities
{
a = 1,
b = 2,
c = 4,
d = 8
}
With this you can assign a number of enum elements that apply.
MYCompatibility comp = MYCompatibility.a | MYCompatibility.b;
|
is a logical OR
and it means that your variable comp
has the properties a
as well as b
You can find out whether a certain compatibility is set via bit comparison:
if (comp & MYCompatibility.a= != 0)
or with the logic provided by the [Flags]
attribute:
if (comp.HasFlag(MYCompatibility.a))
For the inner workings of this, google for bit flags.
Upvotes: 0
Reputation: 2291
I would suggest you to use enums together with extension methods. Let me explain how this would work for you.
public enum Person
{
John = 1,
Kevin = 2,
Michelle = 3,
Krystal = 4,
Leslie = 5
}
Here you have identifiers with an associated number set explicitly. However, this number association is optional and can be elided.
public static class PersonExtensions
{
private Dictionary<Person,List<Person>> compatiblePersons = createCompatiblePersons();
private static Dictionary<Person,List<Person>> createCompatiblePersons()
{
var d = new Dictionary<Person,List<Person>>;
// put your compatibilities here
d[Person.John] = new List()
{
Person.Kevin,
Person.Krystal
};
return d;
}
public static List<Person> GetCompatiblePersons(this Person person)
{
return compatiblePersons(person);
}
public static bool IsCompatibleWith(this Person person, Person other)
{
return this.GetCompatiblePersons().Contains(other);
}
}
This static class
allows to use extension methods on any Person
instance, e.g. Person.John.IsCompatibleWith(Person.Michelle)
will return false
in this case. The association is made in the Dictionary
declared above. This technique allows you to add "properties" to your enums like the ability to ask for compatibility or get the list of compatible persons. However, i would suggest to choose a class if it gets more complex than this.
The answer of @OwlSolo in contrast does the job but is somewhat limited, but if your requirements are just as described I would recommend just adding a convenience extension method, which hides the logical bit calculations and take the [Flags]
approach.
Code written blindly, so no warranties for compilation errors
Upvotes: 0