简体   繁体   中英

Singleton inheriting List<T>

I structured my class like this:

public class MyList: List<MyClass>
{
    internal static bool isConfigured;

    // singleton
    public MyList()
    {
        if (!MyList.isConfigured)
        {
            lock ("isConfigured")
            {
                if (!MyList.isConfigured)
                {
                    // add some elements to MyList parsing them from an XML
                    [..]

                    MyList.isConfigured = true;
                }
            }
        }
    }

    public static MyClass MyStaticMethod(int argument)
    {
        foreach (MyClass c in new MyList())
        {
            // do something
        }
        return // an instance of MyClass
    }

}

When I call MyList.MyStaticMethod() from outside the singleton, I get the following exception:

[..]
MyClass mc = MyList.MyStaticMethod(1));
[..]

An object reference is required for the non-static field, method, or property 'MyList.get'

How can I solve this problem? What is the best why to lay down a singleton class based on List? Thanks

Like any other singleton.

public class MyList: List<MyClass> {
  private readonly static MyList instance = new MyList();

  private MyList() { }

  public static MyList Instance 
  { 
    get 
    {
       return instance;
    }
  }
}

Based on the error message:

An object reference is required for the non-static field, method, or property 'MyList.get'

I think this is simply a case where you have a name collision, for example:

class Foo {
    static void Bar() {
        MyClass mc = MyList.MyStaticMethod(1); // your erroring line
    }
    string MyList {get;set;} // the data-type is not important here
}

in which case the fix is to qualify where you mean the type MyList vs the local member MyList :

MyClass mc = SomeNamespace.MyList.MyStaticMethod(1); // your erroring line

where SomeNamespace is the namespace of your MyList class, or if it is the root namespace:

MyClass mc = global::MyList.MyStaticMethod(1); // your erroring line

Note: I can't get this to error quite in the way described, but the fact that it is talking about a property-accessor makes me think this is likely related.

You cannot achieve singleton with inheritance. You must have a static composite field to make your singleton to work.

When you constructor being called, you are actually creating a new instance of MyList and having a static field isConfigured .

As prescribed as best practice about your problem is to have a Factory Method which will give you an instance of your MyList with your added flavor.

To what you are seeking for is to implement from IList<T> and make the use of List where it's basically a static kind of list.

public class MyList: IList<MyClass>
{
    private static MyList _myList = null;

    private MyList()
    {

    }

    //This is the factory method
    public static MyList GetInstance(int args)
    {
        return _myList ?? (_myList = new MyList());
    }

    public IEnumerator<MyClass> GetEnumerator()
    {
        return _myList.GetEnumerator();
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        return GetEnumerator();
    }

    public void Add(MyClass item)
    {
        _myList.Add(item);
    }

    public void Clear()
    {
        _myList.Clear();
    }

    public bool Contains(MyClass item)
    {
        return _myList.Contains(item);
    }

    public void CopyTo(MyClass[] array, int arrayIndex)
    {
        _myList.CopyTo(array, arrayIndex);
    }

    public bool Remove(MyClass item)
    {
        return _myList.Remove(item);
    }

    public int Count
    {
        get { return _myList.Count; }
    }

    public bool IsReadOnly
    {
        get { return _myList.IsReadOnly; }
    }

    public int IndexOf(MyClass item)
    {
        return _myList.IndexOf(item);
    }

    public void Insert(int index, MyClass item)
    {
        _myList.Insert(index, item);
    }

    public void RemoveAt(int index)
    {
        _myList.RemoveAt(index);
    }

    public MyClass this[int index]
    {
        get { return _myList[index]; }
        set { _myList[index] = value; }
    }
}

USAGE

MyList myList = MyList.GetInstance();
var myClass = new MyClass();
myList.Add(myClass);
Assert.Equal(myClass, myList[0]); // yields true
// Now you basically an instance of List<MyClass>
// and which is singleton.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM