Casting C# out parameters?

Viewed 24695

Is it possible to cast out param arguments in C#? I have:

Dictionary<string,object> dict;  // but I know all values are strings
string key, value;

Roughly speaking (and if I didn't have static typing) I want to do:

dict.TryGetValue(key, out value);

but this obviously won't compile because it "cannot convert from 'out string' to 'out object'".

The workaround I'm using is:

object valueAsObject;
dict.TryGetValue(key, out valueAsObject);
value = (string) valueAsObject;

but that seems rather awkward.

Is there any kind of language feature to let me cast an out param in the method call, so it does this switcheroo for me? I can't figure out any syntax that'll help, and I can't seem to find anything with google.

7 Answers

I spy with my little eye an old post that was still active a month ago... Here's what you do:

public static class DictionaryExtensions
{
    public static bool TryGetValueAs<Key, Value, ValueAs>(this IDictionary<Key, Value> dictionary, Key key, out ValueAs valueAs) where ValueAs : Value
    {
        if(dictionary.TryGetValue(key, out Value value))
        {
            valueAs = (ValueAs)value;
            return true;
        }

        valueAs = default;
        return false;
    }
}

And because compilers are great, you can just call it like this:

dict.TryGetValueAs(key, out bool valueAs); // All generic types are filled in implicitely! :D

But say you're not creating a blackboard AI and just need to call this operation the one time. You can simply do a quicksedoodle inliner like this:

var valueAs = dict.TryGetValue(key, out var value) ? (bool)value : default;

I know these answers have been given already, but they must be pretty old because there is no cool hip modern inlining going on to condense these methods to the size we really want: no more than 1 line.

It is possible by using the Unsafe.As<TFrom, TTo>(ref TFrom source) method to do the cast inline.

var dict = new Dictionary<string, int>
{
    ["one"] = 1,
    ["two"] = 2,
    ["three"] = 3,
};

long result = 0;
dict.TryGetValue("two", out Unsafe.As<long, int>(ref result));

Depending on which platform you are on, this may require you to add a reference to System.Runtime.CompilerServices.Unsafe.

Related