Knapsack performance issue
Instead of storing the actual values in a tuple as the key in a dictionary for memoisation, multiplex them together into a single value and use that as the key. You will need to pick multiplex value that is an order of magnitude higher than the largest &quot;numberOfItemsToConsider&quot; you can expect. Or you could turn them into strings and concat for the key.
i.e.
var key = (weightLeft * 10_000) + numberOfItemsToConsider; // parens for readability.
// OR
var key = weightLeft.ToString() + &quot;_&quot; + numberOfItemsToConsider.ToString(); // parens for readability.

EDIT: Thanks @Jeff E for correcting me on this, Hashtable is slower.
Instead of a dictionary, you could use a hashtable, which is faster. i.e.
Finally, if you're chasing every little bit of time, allocate all your variables outside of any loops, so they are not continually being reallocated, which has an expense.