Search code examples
c#lambdafuncout-parameters

Accessing the out parameter of a Function when it is invoked through a Func


Apologies I haven't done very well with the title of the question, hopefully it will be apparenent with some code

I've created a class that stores poker hand information as follows

public class BestHandSummary<T>
{
    public Func<T, bool> Test { get; set; }
    public Ranking Rank { get; set; } //Enum: Nothing, TwoPair, Straight, Flush, Poker :in ascending order
    public int BestCard { get; set; }
    public BestHand(Ranking r)
    {
        Rank = r;
    }
    ..//default ctor
}

I initialised the rules collection in order of most valuable hand so that when I take the First() of the matched rules the most powerful hand will be chosen as best hand.

rules = new List<BestHandSummary<PokerHand>>()
{
    new BestHandSummary<PokerHand> { Test = h => h.HandContainsFourOfAKind(out bestCard), 
                              Rank = Ranking.FourOfAKind,
                              BestCard = bestCard },
    new BestHandSummary<PokerHand> { Test = h => h.HandContainsFlush(), 
                              Rank = Ranking.Flush },
    new BestHandSummary<PokerHand> { Test = h => h.HandContainsStraight(out bestCard), 
                              Rank = Ranking.Straight,
                              BestCard = bestCard },
    new BestHandSummary<PokerHand> { Test = h => h.HandContainsTwoPair(out bestCard), 
                                      Rank = Ranking.Straight,
                                      BestCard = bestCard },

};
private BestHandSummary<PokerHand> GetAPlayersBestHand(PokerHand hand)
{
   bool hasAny = rules.Any(r => r.Test(hand));
   if (hasAny)
   {
       return rules.Where(r => r.Test(hand) == true).First();
   }
   return new BestHandSummary<PokerHand>(Ranking.Nothing);
}

What I can't seem to figure out is how can I tunnel the out param bestCard into the BestCard property of the BestHandSummary class? The code above doesn't work, BestCard = bestCard doestn't get assigned, which I can understand why, but I'm wondering if there is any small change I can make to fix it..


Solution

  • int bestCard;
    
    new BestHand<PokerHand> { Test = h => h.HandContainsFourOfAKind(out bestCard), 
                                  Rank = Ranking.FourOfAKind,
                                  BestCard = bestCard },
    

    This code won't work, because HandContainsFourOfAKind was never called, and so nothing was assigned to bestCard.

    I'm only interested in bestCard when the rule matched. It is used for when there is a draw between two players. E.G. H= 22KJJ -> best card is Jack, not king

    So, you want BestCard to be assigned only when Test is invoked? This will do.

    var hand = new BestHand<PokerHand> {Rank = Ranking.FourOfAKind};
    hand.Test = h => 
         {
            int bestCard; //var local to the lambda's scope
            bool contains = h.HandContainsFourOfAKind(out bestCard);
            hand.BestCard = bestCard;
            return contains;
         };