-1

I have a class with an indexer:

public class SpecialArray<T> 
{
    public T this[long index]
    {   
       get { return SpecialGetFunction(index) }
       set { SpecialSetFunction(index, value); }
    }

    private void SpecialSetFunction(long index, T value) { ...blah blah... }
    private T SpecialGetFunction(long index) { ...blah blah... }
}

I have another class that currently has an array in it:

public class BaseClass<T>
{
    private T[] _actual_nodes;

    public virtual T[] Nodes 
    {   
       get { return _actual_nodes; }
       set { _actual_nodes = value; }
    }
}

Now I want to override BaseClass<T> so it will use my indexed class, rather than the _actual_nodes array.

public class SomeDerivedClass<T> : BaseClass<T>
{
    private SpecialArray<T> _new_nodes_array;

    public override T[] Nodes 
    {   
        get { return _new_nodes_array; }
        set { _new_nodes_array = value; } 
    }
}

Unfortunately, this last class generates a compiler error, stating it cannot implicitly convert from type SpecialArray<T> to T[] (and vice versa)

So I’m just not sure how to make the get/set statement use my indexed class, rather than an array. At first I was wondering if there is there anyway to reference the index passed to the get/set for "Nodes"? But, even if there is, using it would still only allow me to get/set a single T element, not an array of T[].

QUESTION:
Anyone have thoughts on how can I make the overridden T[] Nodes{} accessor use my indexed class to get/set values?

More academically, WHY doesn't an indexer, returning/accepting a variable of type X, IMPLY a conversion to an array of type X? Can such a conversion be explicitly defined somehow?

Constraint: I cannot make changes to the BaseClass.

AAlferez
  • 1,480
  • 1
  • 22
  • 48
Glurth
  • 290
  • 1
  • 17

2 Answers2

1

If you can convert to/from T[], then use conversion operators:

public class SpecialArray<T> 
{
   public static explicit operator SpecialArray<T>(T[] array) { /* conversion logic here */ }
   public static explicit operator T[](SpecialArray<T> array) { /* conversion logic here */ }

   // the rest of class here
}

public class SomeDerivedClass<T> : BaseClass<T>
{
    private SpecialArray<T>   _new_nodes_array;
    public override T[] Nodes 
    {   
        get{ return (T[])_new_nodes_array; }
        set{ _new_nodes_array= (SpecialArray<T>)value; }  
    }
}

WHY doesn't an indexer, returning/accepting a variable of type X, IMPLY a conversion to an array of type X?

Indexer is just a syntax sugar for the couple of methods:

T get_Item(long index);
void set_Item(T value, long index);

I can't imagine, how this can be converted to array.

Dennis
  • 37,026
  • 10
  • 82
  • 150
0

WHY doesn't an indexer, returning/accepting a variable of type X, IMPLY a conversion to an array of type X

Because arrays can do things besides just use an indexer. For example, you can ask one for its length. Classes that have an indexer can also have functionality that arrays don't, so you can't implicitly convert any class with an indexer to/from an array.

It looks like what you want to do is be able to add the generic constraint that a given generic argument has an indexer. You can't do that. It's simply not a feature of the language, in much the same way that you can't add a generic constraint that a class overloads any other operator.

If you, personally, know how to turn an array of type T into a SpecialArray of type T then you can provide that conversion yourself in the get/set methods of SomeDerivedClass's indexer (or call out to implementations elsewhere). This would need to be entirely explicit based on your personal knowledge of how to transform one type into the other. It wouldn't be able to be implicit.

Community
  • 1
  • 1
Servy
  • 202,030
  • 26
  • 332
  • 449
  • "Because arrays can do things besides just use an indexer. For example, you can ask one for its length." Interesting; so, can I derive the SpecialArray class from IDontKnowWhatClass, to achive the functionality needed to make this behive like an array, in all respects? – Glurth Feb 26 '14 at 21:40
  • @Glurth No, you cannot. Even if you supplied all of the necessary components (which, for the record, you physically can't. I.e., you cannot implement covariance as arrays can) the compiler wouldn't have any way of verifying that you have implemented all of the necessary components. In just the same way that if you create two classes that have the same fields, you still can't implicitly convert one to the other, you need to explicitly define how to convert one to the other. – Servy Feb 26 '14 at 21:46
  • Darn, I wanted to mark this as an answer too, it really enhances the more technical answer that Dennis provided, sorry. – Glurth Feb 27 '14 at 18:28
  • @Glurth So you *really* needed someone to type out the signature for two methods, to convert an array to your type and back? You couldn't figure that out on your own, after being told that that's what you needed to do? I find that...surprising. – Servy Feb 27 '14 at 18:37
  • No Sir. The critical part of the post, I marked as the answer, stated "Indexer is just a syntax sugar for the couple of methods...". This appeared to be the main technical reason I could not do what I was trying. I sorry, but I don't understand what you mean by "after being told.."; his was the first post. "that's what you needed to do": but we determined this could NOT be done, right? – Glurth Feb 27 '14 at 18:46