How to get around lack of covariance with IReadOnlyDictionary? - c#

I'm trying to expose a read-only dictionary that holds objects with a read-only interface. Internally, the dictionary is write-able, and so are the objects within (see below example code). My problem is that IReadOnlyDictionary doesn't support covariant conversions because of the reason outlined in the question here. This means I can't just expose my internal dictionary as a read only one.
So my question is, is there an efficient way to convert my internal dictionary to an IReadOnlyDictionary, or some other way to handle this? The options I can think of are:
Hold two internal dictionaries and keep them in sync.
Create a new dictionary when the property is accessed and cast all the objects within.
Cast the IReadOnly's back to NotReadOnly when using it internally.
1 seems like a pain, 2 seems highly inefficient. 3 sounds like the most promising at the moment, but is still ugly. Do I have any other options?
public class ExposesReadOnly
{
private Dictionary<int, NotReadOnly> InternalDict { get; set; }
public IReadOnlyDictionary<int, IReadOnly> PublicList
{
get
{
// This doesn't work...
return this.InternalDict;
}
}
// This class can be modified internally, but I don't want
// to expose this functionality.
private class NotReadOnly : IReadOnly
{
public string Name { get; set; }
}
}
public interface IReadOnly
{
string Name { get; }
}

You could write your own read-only wrapper for the dictionary, e.g.:
public class ReadOnlyDictionaryWrapper<TKey, TValue, TReadOnlyValue> : IReadOnlyDictionary<TKey, TReadOnlyValue> where TValue : TReadOnlyValue
{
private IDictionary<TKey, TValue> _dictionary;
public ReadOnlyDictionaryWrapper(IDictionary<TKey, TValue> dictionary)
{
if (dictionary == null) throw new ArgumentNullException("dictionary");
_dictionary = dictionary;
}
public bool ContainsKey(TKey key) { return _dictionary.ContainsKey(key); }
public IEnumerable<TKey> Keys { get { return _dictionary.Keys; } }
public bool TryGetValue(TKey key, out TReadOnlyValue value)
{
TValue v;
var result = _dictionary.TryGetValue(key, out v);
value = v;
return result;
}
public IEnumerable<TReadOnlyValue> Values { get { return _dictionary.Values.Cast<TReadOnlyValue>(); } }
public TReadOnlyValue this[TKey key] { get { return _dictionary[key]; } }
public int Count { get { return _dictionary.Count; } }
public IEnumerator<KeyValuePair<TKey, TReadOnlyValue>> GetEnumerator()
{
return _dictionary
.Select(x => new KeyValuePair<TKey, TReadOnlyValue>(x.Key, x.Value))
.GetEnumerator();
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return this.GetEnumerator();
}
}

I would suggest that you might want to define your own covariant interfaces, and include covariant access methods as well as a method which will create a read-only wrapper object which implements either IDictionary or IReadonlyDictionary with the desired types. Simply ignore IEnumerable<KeyValuePair<TKey,TValue>> within your interface.
Depending upon what you're doing, it may be helpful to define an IFetchByKey<out TValue> which is inherited by IFetchByKey<in TKey, out TValue>, with the former accepting queries for any type of object (given an object instance, a collection of Cat should be able to say whether it contains that instance, even if it's a type Dog or ToyotaPrius; the collection won't contain any instances of the latter types, and should be able to say so).

Maybe this solutions works for you:
public class ExposesReadOnly
{
private IDictionary<int, IReadOnly> InternalDict { get; set; }
public IReadOnlyDictionary<int, IReadOnly> PublicList
{
get
{
IReadOnlyDictionary<int, IReadOnly> dictionary = new ReadOnlyDictionary<int, IReadOnly>(InternalDict);
return dictionary;
}
}
private class NotReadOnly : IReadOnly
{
public string Name { get; set; }
}
public void AddSomeValue()
{
InternalDict = new Dictionary<int, NotReadOnly>();
InternalDict.Add(1, new NotReadOnly() { Name = "SomeValue" });
}
}
public interface IReadOnly
{
string Name { get; }
}
class Program
{
static void Main(string[] args)
{
ExposesReadOnly exposesReadOnly = new ExposesReadOnly();
exposesReadOnly.AddSomeValue();
Console.WriteLine(exposesReadOnly.PublicList[1].Name);
Console.ReadLine();
exposesReadOnly.PublicList[1].Name = "This is not possible!";
}
}
Hope this helps!
Greets

Depending on your use case, you might be able to get away with exposing a Func<int,IReadOnly>.
public class ExposesReadOnly
{
private Dictionary<int, NotReadOnly> InternalDict { get; set; }
public Func<int,IReadOnly> PublicDictionaryAccess
{
get
{
return (x)=>this.InternalDict[x];
}
}
// This class can be modified internally, but I don't want
// to expose this functionality.
private class NotReadOnly : IReadOnly
{
public string Name { get; set; }
}
}
public interface IReadOnly
{
string Name { get; }
}

Another approach for a specific lack of covariance:
A work around for a specific type of useful covariance on idictionary
public static class DictionaryExtensions
{
public static IReadOnlyDictionary<TKey, IEnumerable<TValue>> ToReadOnlyDictionary<TKey, TValue>(
this IDictionary<TKey, List<TValue>> toWrap)
{
var intermediate = toWrap.ToDictionary(a => a.Key, a =>a.Value!=null? a.Value.ToArray().AsEnumerable():null);
var wrapper = new ReadOnlyDictionary<TKey, IEnumerable<TValue>>(intermediate);
return wrapper;
}
}

Related

IComparer<T> implementation trouble for sorting a List<T>

I'm having some trouble creating my own List structure. I'm trying to create a List structure called SortedList. The objective is for it to Sort its items as soon as add a new item. This list will not get too big in the project I'm using it for (maybe 50-100 items at most). However, I was testing by adding a simple item of class Employee which has a Name property. And I want this SortedList to sort on employee's Name.
Here is my attempt.
The Employee class
public class Employee : IComparer<Employee>
{
public string Name { get; set; }
public Employee()
{
}
public int Compare(Employee x, Employee y)
{
return string.Compare(x.Name, y.Name,true);
}
}
Here is the SortedList class that I'm trying to create.
public class SortedList<T> : IEnumerable<T>
{
private List<T> _list;
public List<T> List
{
get { return _list; }
set { _list = value; }
}
private Employee EmployeeComparer = new Employee();
public SortedList()
{
_list = new List<T>();
}
public void Insert(T item)
{
if (!_list.Contains(item))
{
_list.Add(item);
Sort(_list);
}
}
private void Sort(List<T> list)
{
var type = typeof(T);
switch (type.Name)
{
case "Int32":
case "String":
list.Sort();
break;
case "Employee":
Employee EmployeeComparer = new Employee();
list.Sort(EmployeeComparer);
break;
}
}
public IEnumerator<T> GetEnumerator()
{
return _list.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
From program.cs I'm basically populating the SortedList with three instances of Employee objects and I expect it to Sort it by employee's Name property and in the out put I expect to see this.
Barry
Neil
Zach
class Program
{
static void Main(string[] args)
{
SortedList<Employee> list = new SortedList<Employee>();
list.Insert(new Employee() { Name="Zach"});
list.Insert(new Employee() { Name = "Neil" });
list.Insert(new Employee() { Name = "Barry" });
foreach (var item in list)
{
Console.WriteLine(item.Name);
}
}
}
But I get a compiler error. It says:
Severity Code Description Project File Line Suppression State
Error CS1503 Argument 1: cannot convert from 'ExtensingLists.Employee' to 'System.Collections.Generic.IComparer<T>' ExtensingLists C:\E Drive\VSProjects\C-Sharp Generics Course\ExtensingLists\ExtensingLists\SortedList.cs 57 Active
The error says line 57, which is this:
list.Sort(EmployeeComparer);
What am I doing wrong? Please advise. Thank you.
The concrete question you're asking about is like asking why
int f(object o) { return o is int ? o : 0; }
fails to compile. Even if you've checked that o has type int at run-time, at compile-time it still has type object, which means it can't be used as the return value. You'd need a cast to get that working:
int f(object o) { return o is int ? (int)o : 0; }
and the same applies to your code.
But there's something more fundamentally wrong. Your Employee shouldn't be implementing IComparer<Employee>. It should be implementing IComparable<Employee>, which specifies not that an Employee object knows how to compare two other Employee objects, but that it knows how to compare itself to another Employee object. And when you do that, you should be able to just call list.Sort(); without checking the type at all.
The List.Sort method can be made to work in multiple ways.
This method uses the default comparer Comparer.Default for type T to determine the order of list elements. The Comparer.Default property checks whether type T implements the IComparable generic interface and uses that implementation, if available. If not, Comparer.Default checks whether type T implements the IComparable interface. If type T does not implement either interface, Comparer.Default throws an InvalidOperationException.
So by making the below change, it will start working for you
public class Employee : IComparable<Employee> {
public string Name { get; set; }
public Employee() {
}
public int CompareTo(Employee other) {
return string.Compare(Name, other.Name, true);
}
}
and the Below change in public class SortedList<T> : IEnumerable<T> {
private static void Sort(List<T> list) {
var type = typeof(T);
list.Sort();
}
This is not the only way to do, but a preferable way to do when the Types are intrinsically Orderable. You can also use the IComparer<T> interface, but that is used when the Type needs to be sorted in a way that IComparable<T> does not or when the Type is not an IComparable<T>. I have listed all the code here together
class Program {
static void Main() {
SortedList<Employee> list = new SortedList<Employee>();
list.Insert(new Employee() { Name = "Zach" });
list.Insert(new Employee() { Name = "Neil" });
list.Insert(new Employee() { Name = "Barry" });
foreach (var item in list) {
Console.WriteLine(item.Name);
}
}
}
public class Employee : IComparable<Employee> {
public string Name { get; set; }
public int Age { get; set; }
public Employee() {
}
public int CompareTo(Employee other) {
return string.Compare(Name, other.Name, true);
}
}
public class EmployeeAgeComparer : IComparer<Employee> {
public int Compare(Employee x, Employee y) {
return x.Age - y.Age;
}
}
public class SortedList<T> : IEnumerable<T> {
private List<T> _list;
public List<T> List {
get { return _list; }
set { _list = value; }
}
private EmployeeAgeComparer EmployeeComparer = new EmployeeAgeComparer();
public SortedList() {
_list = new List<T>();
}
public void Insert(T item) {
if (!_list.Contains(item)) {
_list.Add(item);
Sort(_list);
}
}
private void Sort(List<T> list) {
if (typeof(T) == typeof(Employee))
list.Sort((IComparer<T>)EmployeeComparer);
else
list.Sort();
}
public IEnumerator<T> GetEnumerator() {
return _list.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator() {
return GetEnumerator();
}
}

Using Attributes to simplify properties

I have a scenario where I need the properties in my class to map to a dictionary. Here is a code sample:
public string Foo
{
get
{
if (!PropertyBag.ContainsKey("Foo"))
{
return null;
}
return PropertyBag["Foo"];
}
set
{
PropertyBag["Foo"] = value;
}
}
I have to apply this pattern to multiple properties. Is there a way to use attributes to do that?
I know that PostSharp would work for this purpose, but I was hoping there is a way to do it without using it.
This feels like a code smell to me. It would be better to use regular POCOs and convert them to a Dictionary only when needed.
public class BlogPost
{
public string Title { get; set; }
public string Body { get; set; }
public int AuthorId { get; set; }
public Dictionary<string, object> ToDictionary()
{
return this.GetType()
.GetProperties(BindingFlags.Instance | BindingFlags.Public)
.ToDictionary(prop => prop.Name, prop => prop.GetValue(this, null));
}
}
Inspiration: How to convert class into Dictionary?
And to be honest, a ToDictionary method on your POCO's seems like a code smell. It would be better to refactor your code so the conversion of POCOs to Dictionaries happens in its own layer, as a service maybe.
Edit: This Gist I found while searching google for "c# convert object to dictionary" could provide a more generalized solution, and probably more bullet proof than my cobbled together example:
Gist: https://gist.github.com/jarrettmeyer/798667
From the Gist:
public static class ObjectToDictionaryHelper
{
public static IDictionary<string, object> ToDictionary(this object source)
{
return source.ToDictionary<object>();
}
public static IDictionary<string, T> ToDictionary<T>(this object source)
{
if (source == null)
ThrowExceptionWhenSourceArgumentIsNull();
var dictionary = new Dictionary<string, T>();
foreach (PropertyDescriptor property in TypeDescriptor.GetProperties(source))
AddPropertyToDictionary<T>(property, source, dictionary);
return dictionary;
}
private static void AddPropertyToDictionary<T>(PropertyDescriptor property, object source, Dictionary<string, T> dictionary)
{
object value = property.GetValue(source);
if (IsOfType<T>(value))
dictionary.add(property.Name, (T)value);
}
private static bool IsOfType<T>(object value)
{
return value is T;
}
private static void ThrowExceptionWhenSourceArgumentIsNull()
{
throw new ArgumentNullException("source", "Unable to convert object to a dictionary. The source object is null.");
}
}
Credit: jerrettmeyer at GitHub
This should add a ToDictionary method to every object.
Edit: From the following comment
To give a bit of context, I am using Entity Framework and I have a class hierarchy that I would like to keep in one table while avoiding null columns everywhere.
Entity framework supports multiple table inheritance. That might be a better solution in your case.
You can write a GetValueOrDefault extension method and reduce the code a little.
public static class DictionaryExtensions
{
public static TValue GetValueOrDefault<TKey, TValue>(this IDictionary<TKey,TValue> self, TKey key)
{
TValue value;
self.TryGetValue(key,out value);
return value;
}
}
public string Foo
{
get
{
return PropertyBag.GetValueOrDefault("Foo");
}
set
{
PropertyBag["Foo"] = value;
}
}
You can eliminate the magic strings using expressions.
If you're using at least .NET 4.5 then you have the CallerMemberNameAttribute which you could use like this:
class SomeClass
{
public string Foo
{
get
{
return GetPropertyValue();
}
set
{
SetPropertyValue( value );
}
}
private string GetPropertyValue( [CallerMemberName] string name = null )
{
string value;
PropertyBag.TryGetValue( name, out value );
return value;
}
private void SetPropertyValue( string value, [CallerMemberName] string name = null )
{
PropertyBag[name] = value;
}
}
This will result in the compiler filling out the name of the member for you. If you're not (or otherwise can't) use .NET 4.5, another alternative would be to take advantage of expression trees as suggested in another answer.
class Test
{
Dictionary<string,object> _values = new Dictionary<string, object>();
public string Foo
{
get
{
var value = GetValue();
return value == null ? string.Empty : (string)value;
}
set
{
SetValue(value);
}
}
private object GetValue()
{
var stack = new StackTrace();
var key = GetGenericName(stack.GetFrame(1).GetMethod().Name);
if (_values.ContainsKey(key)) return _values[key];
return null;
}
private void SetValue(object value)
{
var stack = new StackTrace();
var key = GetGenericName(stack.GetFrame(1).GetMethod().Name);
_values[key] = value;
}
private string GetGenericName(string key)
{
return key.Split('_')[1];
}
}

Creating a JavascriptConverter for a Generic Type

Suppose I have a generic class called MyClass<T> how can I create a JavascriptConverter that will be used for any T possible (be it MyClass<OtherClass>, MyClass<SimpleClass>)?
I tried to to the following in my converter:
public Enumerable<Type> SupportedTypes
{
get
{
return new List<Type>(){ typeof(MyClass<>) };
}
}
But to no avail.
Any ideas? is this possible?
If not, is there any other way to acheive the same result?
If you really want this, with no filters at all:
using System.Linq;
....
var concreteGenericTypes =
(from assembly in AppDomain.CurrentDomain.GetAssemblies()
from T in assembly.GetTypes()
where T.IsClass && T.GetConstructor(new Type[] { }) != null
select typeof(MyClass<>).MakeGenericType(T)).ToList();
It gets all loaded assemblies, then all types for those assemblies, then filters according to your generic where conditions, finally it makes a concrete generic type from your class and the type.
If you are the author of the generic type, you should create an interface that your generic type inherits from. For example:
public interface IResultSet
{
long TotalItems { get; }
IEnumerable Items { get; }
}
public class ResultSet<T> : IResultSet, IEnumerable<T>
{
private IEnumerable<T> _enumerable;
private int _totalItems;
public ResultSet(IEnumerable<T> enumerable,
int totalItems)
{
_enumerable = enumerable;
_totalItems = totalItems;
}
public IEnumerable Items { get { return _enumerable; } }
public long TotalItems { get{ return _totalItems; } }
public IEnumerator<T> GetEnumerator()
{
return _enumerable.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return _enumerable.GetEnumerator();
}
}
public class ResultSetConverter : JavaScriptConverter
{
public override IEnumerable<Type> SupportedTypes
{
get
{
return new[] { typeof(IResultSet) };
}
}
...
public override IDictionary<string, object> Serialize(object obj, JavaScriptSerializer serializer)
{
if (!typeof(IResultSet).IsAssignableFrom(obj.GetType()))
{
return null;
}
var resultSet = obj as IResultSet;
var json = new Dictionary<string, object>();
json["totalItems"] = resultSet.TotalItems;
json["items"] = resultSet.Items;
return json;
}
}
As far as I can think of, as javascript is loosely typed, so having something as generic parameters is not a concern.
You can try and test using instanceof, though.
check this question:
What is the instanceof operator in JavaScript?
It does what you need, at least the checking type part.

How to expose read-only collection another type of private collection?

Here is my problem: there is a class that contains a inner collection (or list, or array, or something like this) of some some class and It must expose a public read-only collection of items, which are properties (or fields) of relative items in inner collection. For example:
//Inner collection consists of items of this class
class SomeClass
{
public int _age;
//This property is needed for exposing
public string Age { get { return this._age.ToString(); } }
}
//Keeps inner collection and expose outer read-only collection
class AnotherClass
{
private List<SomeClass> _innerList = new List<SomeClass> ();
public ReadOnlyCollection<string> Ages
{
get
{
//How to implement what i need?
}
}
}
I know a simple way to do this by the use of a pair of inner lists, where the second keeps values of needed properties of first. Something like this:
//Inner collection consists of items of this class
class SomeClass
{
public int _age;
//This property is needed for exposing
public string Age { get { return this._age.ToString(); } }
}
//Keeps inner collection and expose outer read-only collection
class AnotherClass
{
private List<SomeClass> _innerList = new List<SomeClass> ();
private List<string> _innerAgesList = new List<string> ();
public ReadOnlyCollection<string> Ages
{
get
{
return this._innerAgesList.AsreadOnly();
}
}
}
But I dislike this overhead. May be there is some way to do what I want with exposing interfaces. Help me, please!
Hurra!
It seems that the best solution has been found. Due to the post of Groo
this problem found its almost universal answer. Here is It (we need to add two entity):
public interface IIndexable<T> : IEnumerable<T>
{
T this[int index] { get; }
int Count { get; }
}
class Indexer <Tsource, Ttarget> : IIndexable<Ttarget>
{
private IList<Tsource> _source = null;
private Func<Tsource, Ttarget> _func = null;
public Indexer(IList<Tsource> list, Func<Tsource, Ttarget> projection)
{
this._source = list;
this._func = projection;
}
public Ttarget this[int index] { get { return this._func(this._source[index]); } }
public int Count { get { return _source.Count; } }
IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); }
public IEnumerator<Ttarget> GetEnumerator()
{ foreach (Tsource src in this._source) yield return this._func(src); }
}
With them, our implementation looks like this:
//Inner collection consists of items of this class
class SomeClass
{
public int _age;
//This property is needed for exposing
public string Age { get { return this._age.ToString(); } }
}
//Keeps inner collection and expose outer read-only collection
class AnotherClass
{
private List<SomeClass> _innerList = new List<SomeClass> ();
private Indexer<SomeClass, string> _indexer = null;
public AnotherClass ()
{ this._indexer = new Indexer<SomeClass, string > (this._innerList, s => s.Age); }
public IIndexable<string> Ages { get { return this._indexer; } }
}
Thank Groo and the rest who answered. Hope, this helps someone else.
The overhead is not so significant if you consider that ReadOnlyCollection is a wrapper around the list (i.e. it doesn't create a copy of all the items).
In other words, if your class looked like this:
class AnotherClass
{
private ReadOnlyCollection<string> _readonlyList;
public ReadOnlyCollection<string> ReadonlyList
{
get { return _readonlyList; }
}
private List<string> _list;
public List<string> List
{
get { return _list; }
}
public AnotherClass()
{
_list = new List<string>();
_readonlyList = new ReadOnlyCollection<string>(_list);
}
}
Then any change to the List property is reflected in the ReadOnlyList property:
class Program
{
static void Main(string[] args)
{
AnotherClass c = new AnotherClass();
c.List.Add("aaa");
Console.WriteLine(c.ReadonlyList[0]); // prints "aaa"
c.List.Add("bbb");
Console.WriteLine(c.ReadonlyList[1]); // prints "bbb"
Console.Read();
}
}
You may have issues with thread safety, but exposing IEnumerable is even worse for that matter.
Personally, I use a custom IIndexable<T> interface with several handy wrapper classes and extension method that I use all over my code for immutable lists. It allows random access to list elements, and does not expose any methods for modification:
public interface IIndexable<T> : IEnumerable<T>
{
T this[int index] { get; }
int Length { get; }
}
It also allows neat LINQ-like extension methods like Skip, Take and similar, which have better performance compared to LINQ due to the indexing capability.
In that case, you can implement a projection like this:
public class ProjectionIndexable<Tsrc, Ttarget> : IIndexable<Ttarget>
{
public ProjectionIndexable
(IIndexable<Tsrc> src, Func<Tsrc, Ttarget> projection)
{
_src = src;
_projection = projection;
}
#region IIndexable<Ttarget> Members
public Ttarget this[int index]
{
get { return _projection(_src[index]); }
}
public int Length
{
get { return _src.Length; }
}
#endregion
#region IEnumerable<Ttarget> Members
// create your own enumerator here
#endregion
}
And use it like this:
class AnotherClass
{
private IIndexable<string> _readonlyList;
public IIndexable<string> ReadonlyList
{
get { return _readonlyList; }
}
private List<SomeClass> _list;
public List<SomeClass> List
{
get { return _list; }
}
public AnotherClass()
{
_list = new List<SomeClass>();
_readonlyList = new ProjectionIndexable<SomeClass, string>
(_list.AsIndexable(), c => c.Age);
}
}
[Edit]
In the meantime, I posted an article describing such a collection on CodeProject. I saw you've implemented it yourself already, but you can check it out nevertheless and reuse parts of the code where you see fit.
Why don't you just return IEnumerable?
If you have access to LINQ (.NET 3.5) then just use a select()
public IEnumerable<string> Ages{
get{
return _innerList.Select(s => s.stringProperty);
}
}
in this case I normaly just use IEnumerable - if the collection is readonly and you don't need the Index-functionality you can just do somehting like this:
public IEnumerable<string> Ages
{
get
{
return this._innerList.Select(someObj => someObj.Age).ToArray();
}
}

Looking for a syntactic shortcut for accessing dictionaries

I have an abstract base class that holds a Dictionary. I'd like inherited classes to be able to access the dictionary fields using a convenient syntax. Currently I have lots of code like this:
string temp;
int val;
if (this.Fields.TryGetValue("Key", out temp)) {
if (int.TryParse(temp, out val)) {
// do something with val...
}
}
Obviously I can wrap this in utility functions but I'd like to have a cool, convenient syntax for accessing the dictionary fields where I can simply say something like:
int result = #Key;
Is there any way to do something like this in C# (3.5)?
You could add an indexer to your class and pass the indexer's parameter through to the dictionary.
class Foo
{
// Initialized elsewhere
Dictionary<String,String> Fields;
public Int32 this[String key]
{
String temp = null;
Int32 val = 0;
if (this.Fields.TryGetValue(key, out temp)) {
Int32.TryParse(temp, out val);
}
return val;
}
}
Then given an instance of Foo called foo you could do this:
Int32 value = foo["Key"];
How about an extension method?
public static int TryGetInt(this IDictionary dict, string key)
{
int val;
if (dict.Contains(key))
{
if (int.TryParse((string)dict[key], out val))
return val;
else
throw new Exception("Value is not a valid integer.");
}
throw new Exception("Key not found.");
}
The closer you can get to a nice syntax is using extension methods:
public static class MyDictExtensionMethods
{
public static T Get<T>(this Dictionary<string, object> dict, string key)
where T: IConvertible
{
object tmp;
if (!dict.TryGetValue(key, out tmp))
return default(T);
try {
return (T) Convert.ChangeType(tmp, typeof(T));
} catch (Exception) {
return default(T);
}
}
}
Usage:
int val = this.Fields.Get<int>("Key");
You can then create additional overloads for specific types (i.e.: types that does not implement IConvertible and need specific conversion).
Assuming that it's not always an int you want (if it is, then why isn't it a Dictionary<string, int>?) - I think something like this works and gets pretty close:
int i = #int["Key"];
string s = #string["Key"];
object o = #object["Key"];
This combines the fact that identifiers can be prefixed with # (it's usually optional, but it's required if your identifier is a reserved keyword, like int or string) with the default indexed parameter from Andrew Hare's answer.
It does require another class to be used to get the indexing - though if you wanted to use parens instead of square brackets for the key name, you could use methods instead:
int i = #value<int>("Key");
Implementation would be something like:
class DerivedClass : BaseClass {
void Main() {
int i = #int["Key"];
}
}
abstract class BaseClass {
private Dictionary<string, string> D { get; set; }
protected Indexer<int> #int = new Indexer<int>(s => int.Parse(s), this);
protected Indexer<string> #string = new Indexer<string>(s => s, this);
protected Indexer<object> #object = new Indexer<object>(s => (object)s, this);
protected class Indexer<T> {
public T this[string key] {
get { return this.Convert(this.BaseClass.D[key]); }
}
private T Convert(string value) { get; set; }
private BaseClass { get; set; }
public Indexer(Func<T, string> c, BaseClass b) {
this.Convert = c;
this.BaseClass = b;
}
}
}
Or, the method route:
class DerivedClass : BaseClass {
void Main() {
int i = #value<int>("key");
}
}
abstract class BaseClass {
private Dictionary<string, string> D { get; set; }
protected T #value<T>(string key) {
string s = this.D[s];
return Convert.ChangeType(s, typeof(T));
}
}
After reading through the language spec - if you're not tied to #, _ is a legal identifier. Combine that with indexers and you get:
int i = _["key"];

Categories

Resources