Get value from Dictionary<string, object> without unboxing?
I was wondering if it's possible to run the following code but without the unboxing line:-
t.Value = (T)x;
Or maybe if there is another way to do this kind of operation?
Here is the full code:-
public class ValueWrapper<T>
{
public T Value { get; set; }
public bool HasValue { get; set; }
public ValueWrapper()
{
HasValue = false;
}
}
class Program
{
static void Main(string[] args)
{
Dictionary<string, obje开发者_StackOverflow中文版ct> myDictionary = new Dictionary<string, object>();
myDictionary.Add("key1", 6);
myDictionary.Add("key2", "a string");
var x2 = GetValue<int>(myDictionary, "key1");
if (x2.HasValue)
Console.WriteLine("'{0}' = {1}", "key1", x2.Value);
else
Console.WriteLine("No value found");
Console.ReadLine();
}
static ValueWrapper<T> GetValue<T>(IDictionary<string, object> dictionary, string key)
{
ValueWrapper<T> t = new ValueWrapper<T>();
object x = null;
if (dictionary.TryGetValue(key, out x))
{
if (x.GetType() == typeof(T))
{
t.Value = (T)x;
t.HasValue = true;
}
}
return t;
}
}
Thanks in advance!!
Richard.
A few comments:
t.Value = (T)x;
The cast is necessary. This is because t.Value
is of type T
and x
is of type object
. The strongly-typed nature of C# requires that you tell the compiler "look, I know this might unsafe but can you just try to do it for me anyway, either by conversion or unboxing or whatever? Thanks!"
2.
object x = null;
if (dictionary.TryGetValue(key, out x)) {
if (x.GetType() == typeof(T)) {
t.Value = (T)x;
t.HasValue = true;
}
}
return t;
What if x
is an instance of a class that derives from T
? Or if x
is an instance of a class that implements an interface and T
is that interface? Right now, you will return a instance of ValueWrapper<T>
that indicates there was no object in the dictionary with the key key
. I would argue this is very counterintuitive to what most people expect.
Additionally, if you're not going to throw up when dictionary
does not contain a value matching the key key
, I think you should rename your method to TryGetValue
, accept a out
parameter of type ValueWrapper<T>
, and return a bool
indicating success/failure.
3.
Responding to your comment, here's one solution.
public interface IValueWrapper {
object Value { get; set; }
bool HasValue { get; set; }
}
public class ValueWrapper<T> : IValueWrapper {
public T Value { get; set; }
object IValueWrapper.Value {
get { return Value; }
set { this.Value = (T)value; }
}
public bool HasValue { get; set; }
public ValueWrapper() {
this.HasValue = false;
}
public ValueWrapper(T value) {
this.Value = value;
this.HasValue = value != null;
}
}
public static class DictionaryExtensions {
public static void Add<T>(
this IDictionary<string, IValueWrapper> dictionary,
string key,
T value
) {
ValueWrapper<T> valueWrapper = new ValueWrapper<T>(value);
dictionary.Add(key, valueWrapper);
}
public static bool TryGetWrappedValue<T>(
IDictionary<string, IValueWrapper> dictionary,
string key,
out ValueWrapper<T> value
) {
IValueWrapper valueWrapper;
if (dictionary.TryGetValue(key, out valueWrapper)) {
value = (ValueWrapper<T>)valueWrapper;
return true;
}
else {
value = null;
return false;
}
}
}
Usage:
var dict = new Dictionary<string, IValueWrapper>();
dict.Add("hello", 5);
ValueWrapper<int> value;
dict.TryGetWrappedValue("hello", out value);
You'll have to add parameter checking etc.
精彩评论