In addition to the great answer provided by Fernando Matsumoto you should consider implementing the equality/hashcode methods/operators. Reference equality isn't how cards are treated in the real world. In the real world it doesn't matter which deck the Jack of Clubs came from it is always a Jack of Clubs.
public class Card : IEquatable<Card>
{
public Card(CardSuit suit, CardRank rank)
{
// Suit and Rank validation logic here
Suit = suit;
Rank = rank;
}
// Replace this with the plain get call like Fernando's answer in C# 6
// You can also leave it and be careful or create a private readonly backing property
public CardSuit Suit { get; private set; }
public CardRank Rank { get; private set; }
public static bool operator ==(Card left, Card right)
{
// Review https://msdn.microsoft.com/en-US/library/ms173147%28v=vs.80%29.aspx
// If both are null, or both are same instance, return true.
if (ReferenceEquals(left, right))
{
return true;
}
// If one is null, but not both, return false.
if (((object)left == null) || ((object)right == null))
{
return false;
}
// Return true if the fields match:
return left.Equals(right);
}
public static bool operator !=(Card left, Card right)
{
return !(left == right);
}
public bool Equals(Card other)
{
if(other == null)
{
return false;
}
return Rank == other.Rank && Suit == other.Suit;
}
public override bool Equals(object obj)
{
return Equals(obj as Card);
}
public override int GetHashCode()
{
return Suit.GetHashCode() ^ Rank.GetHashCode();
}
// Not strictly needed but why not do it....
public override string ToString()
{
// Take advantage of how the Enum.ToString() method functions
return Rank.ToString() + " of " + Suit.ToString();
}
}
Something else you might consider is implementing the IComparable<Card>
interface. That would let you sort a user's hand trivially. I'll leave that exercise to you because I don't want to debate what is the proper suit order1.
1: Even though it is clearly Spades, Diamonds, Clubs, Hearts... ;)