Bart Friederichs
Bart Friederichs

Reputation: 33511

Returning a static array without using a class field

I have the following base and derived (partial, for sake of brevity) classes:

class Base {
     public abstract int[] someArray { get; }
}

class Derived : Base {
     private readonly static int[] _someArray = new int[] { 1,2,3,4 };
     public override int[] someArray { 
         get {
              return _someArray;
         }
     }
}

What I would like now, is put the new int[] { 1,2,3,4 } in the return part of the getter. But, that would create a new array every time the getter is called.

Is it possible to directly return some kind of object, which stays the same for all objects of class Derived ?

Something along the lines of (I know this is invalid C#):

  get {
        return (int[]) { 1, 2, 3, 4 };
  }

Upvotes: 4

Views: 157

Answers (2)

Botz3000
Botz3000

Reputation: 39600

If you only want to put the new int[] { 1,2,3,4 } part into the getter, that's easy...

 private static int[] _someArray = null;
 public override int[] someArray { 
     get {
          return _someArray ?? (_someArray = new int[] { 1,2,3,4 });
     }
 }

You'd lose the readonly then, though.

UPDATE: Generics solution

Or you could abuse the features of generics for that:

// Of course you still want to use the non-generic class Base
abstract class Base {
    public abstract int[] someArray { get; }
}

abstract class Base<T> : Base where T: Base<T> {
     // Will be created once for every T, i.e. every derived class.
     private static int[] _someArray;

     public override int[] someArray {
        get { return _someArray ?? (_someArray = CreateArray()); }
     }

     protected abstract int[] CreateArray();
}

sealed class Derived : Base<Derived> {
     protected sealed override int[] CreateArray() { 
         return new int[] { 1,2,3,4 };
     }
}

sealed class DerivedB : Base<DerivedB> {
    protected sealed override int[] CreateArray() {
        return new int[] { 2,3,4,5 };
    }
}

Note that this only works for one inheritance level, so i sealed some stuff :)

Upvotes: 4

Tim Schmelter
Tim Schmelter

Reputation: 460058

As far as i know that will not work in C#. You can either use a field or create a variable in the property/method. In VB.NET you have the Static keyword for local variables(see below).

You have commented that you have many derived classes and you don't want to have a static field array for each derived class. I would suggest to use a different approach then. You could f.e. use a static Dictionary in your base class and an enum for each derived class:

abstract class Base
{
    public abstract DerivedType Type { get; }

    protected static readonly Dictionary<DerivedType, int[]> SomeDict;

    static Base()
    {
        SomeDict = new Dictionary<DerivedType, int[]>();
        SomeDict.Add(DerivedType.Type1, new int[] { 1, 2, 3, 4 });
        SomeDict.Add(DerivedType.Type2, new int[] { 4, 3, 2, 1 });
        SomeDict.Add(DerivedType.Type3, new int[] { 5, 6, 7 });
        // ...
    }

    public static int[] SomeArray(DerivedType type)
    {
        return SomeDict[type];
    }
}

public enum DerivedType
{
    Type1, Type2, Type3, Type4, Type5
}

class Derived : Base
{
    public override DerivedType Type
    {
        get { return DerivedType.Type1; }
    }
}

In VB.NET, however, it is possible using a static local variable using the Static-keyword:

MustInherit Class Base
    Public MustOverride ReadOnly Property someArray() As Integer()
End Class

Class Derived
    Inherits Base
    Public Overrides ReadOnly Property someArray() As Integer()
        Get
            Static _someArray As Int32() = New Integer() {1, 2, 3, 4}
            Return _someArray
        End Get
    End Property
End Class

_someArray will be the same for every instance of Derived.

Upvotes: 0

Related Questions