7

I have a DICOM dictionary that contains a set of objects all deriving from DataElement. The dictionary has an int as a key, and the DataElement as property. My DICOM dictionary contains a this[] property where I can access the DataElement, like this:

public class DicomDictionary
{
  Dictionary<int, DataElement> myElements = new Dictionary<int, DataElement>();
  .
  .
  public DataElement this[int DataElementTag]
  {
    get
    {
      return myElements[int];
    }
  }
}

A problem now is that I have different DataElement types all deriving from DataElement, like DataElementSQ, DataElementOB and so on. What I wanted to do now is the following to make writing in C# a little bit easier:

 public T this<T>[int DataElementTag] where T : DataElement
 {
   get
   {
      return myElements[int];
   }
 }

But this is not really possible. Is there something I have missed? Of course I could do it with Getter method, but it would be much nicer to have it this way.

msedi
  • 1,437
  • 15
  • 25
  • 1
    You cant have Generic properties (including indexers) http://stackoverflow.com/questions/494827/why-it-is-not-posible-to-define-generic-indexers-in-net – Dean Chalk Aug 12 '11 at 16:16
  • Whether you believe it or not, what you're suggesting doing would be confusing to use and read, imo. – Marc Aug 12 '11 at 16:23

4 Answers4

4

The best options are to either use a generic method (instead of an indexer), or to have your class be generic (in which case, the indexer would be tied to the class generic type). A generic indexer as you've described is not allowed in C#.

Reed Copsey
  • 554,122
  • 78
  • 1,158
  • 1,373
  • Hi Reed, you are right I could create a generic class, but I was trying not to have something like, because currently it's working without a generic class. – msedi Aug 12 '11 at 16:19
  • @msedi: Part of the problem, given what you're showing, is that the Dictionary could contain multiple types - you'd have no way to guarantee type safety in your current code (even if it worked). That being said, the C# spec doesn't support it... – Reed Copsey Aug 12 '11 at 16:20
  • @msedi: If the class itself doesn't know what type the indexer should return then what does? It would be bad design for the caller to know the type and not the class. So what exactly is your use case? Are you going to have instances of this class which only have a single subtype in them? Or were you hoping to have a mix of subtypes and trusting the calling code to know the type that it is getting out? Your design seems a little weird at the moment... – Chris Jul 11 '17 at 23:02
2

Why not use a real generic method GetDataElement<T> where T : DataElement instead? Generic indexers are not supported in C#. Why do you think in this case an indexer is better than a method?

Cheng Chen
  • 42,509
  • 16
  • 113
  • 174
  • Hi Danny, this is what I expected. The problem of having a getter method, and in fact internally I have such a method is that it makes the code much more unreadable then having it as this short-hand method. Of course if I have to cast it, then this is also not the case. This is why I was looking for such a thing. Currently I can live with it, but this question came into my mind. – msedi Aug 12 '11 at 16:17
2

Is it a case for you?

public class DicomDictionary<TElement> 
{
        Dictionary<int, TElement> myElements = new Dictionary<int, TElement>();
        public TElement this[int DataElementTag]   
        {     
              get     
              {       
                 return myElements[int];     
              }   
        } 
}
sll
  • 61,540
  • 22
  • 104
  • 156
  • Hi sllev, maybe I have to think about it. I see that there is no other way, maybe I should do it as you suggested. – msedi Aug 12 '11 at 16:20
0

Append for sll answer is:

public class Acessor<TKey, TValue>
    where TKey : IComparable
    where TValue : class
{
    Dictionary<TKey, TValue> myElements = new Dictionary<TKey, TValue>();

    public TValue this[TKey key]
    {
        get
        {
            return myElements[key];
        }
        set
        {
            myElements.Add(key, value);
        }
    }
}

Or without change the class signature:

 public class Acessor
{
    Dictionary<string, object> myElements = new Dictionary<string, object>();

    public object this[string key]
    {
        get
        {
            return myElements[key];
        }
        set
        {
            myElements.Add(key, value);
        }
    }
}

And create a method to parse for the generic type:

public T Get<T>(string key)
        where T : class
    {
        return (T)Convert.ChangeType(acessor[key], typeof(T));
    }