In a custom interface for keyed collections I need to implement, I want covariance. So the signature of the interface is IKeyedCollection<TKey, out TValue>. I would also like to include a method similar to TryGetValue in this interface, but covariance on out parameters is not allowed for reasons detailed here. Therefore, the following will not work:
interface IKeyedCollection<TKey, out TValue>
{
bool TryGetValue(TKey key, out TValue value);
}
But if it worked, it would be used like this:
IKeyedCollection<string, int> someKeyedCollection = ...;
int result;
if (someKeyedCollection.TryGetValue(out result))
{
...
}
I am looking for alternatives that do the same: try to get a value from the collection without throwing an exception when it fails, and returning whether it succeeded.
Let me explain my train of thought, and how I arrived at code that does the job.
I imagined that a Result<T> struct might do the trick, but of course the following also does not work as Result<T> is not covariant.
struct Result<T>
{
T Value { get; }
bool HasResult { get; }
}
interface IKeyedCollection<TKey, out TValue>
{
Result<TValue> GetValue(TKey key);
}
I could make a covariant interface IResult<T> but this will cause the return value to be boxed, which is something I would like to avoid:
interface IResult<out T> { ... }
struct Result<T> : IResult<T> { ... }
interface IKeyedCollection<TKey, out TValue>
{
IResult<TValue> GetValue(TKey key);
}
I could also switch the boolean and the return value parameters. This is not consistent with the way it is done in the .NET Framework, but does solve all previously mentioned problems.
So, the following code actually works. However, I know how the original TryGetValue works and I like how you can put it in an if. You cannot do that here, the syntax is uglier:
interface IKeyedCollection<TKey, out TValue>
{
TValue GetValue(TKey key, out bool hasResult);
}
IKeyedCollection<string, int> someKeyedCollection = ...;
bool hasResult;
int result = someKeyedCollection.GetValue(out hasResult);
if (hasResult)
{
...
}
So, my questions are essentially: to have a TryGetValue or similar method in a covariant interface, do you know of a better way than the above? I think the syntax is uglier and the interface is less usable. Any suggestions or improvements?