简体   繁体   中英

How do you create an array-like C# constructor that will allow “new MyClass() { obj1, obj2, obj3 };”

I'm trying to create a class that accepts a constructor similar to that of a dictionary, list, or array where you can create the object with a literal collection of objects, though I have been unable to find how to create such a constructor, if it's even possible.

MyClass obj = new MyClass()
{
    { value1, value2 },
    { value3, value4 }
}

You need two things to make collection initializers work:

  1. Implement IEnumerable (non-generic version)
  2. Add() method that matches the collection initializer

Here's an example that looks like IDictionary:

class Program
{
    static void Main(string[] args)
    {
        MyClass obj = new MyClass()
        {
            {value1, value2},
            {value3, value4}
        };
    }
}

public class MyClass : IEnumerable
{
    public void Add(object x, object y)
    {

    }

    public IEnumerator GetEnumerator()
    {
    }
}

Note that the collection initializer code literally translates to this:

MyClass temp = new MyClass();
temp.Add(value1, value2);
temp.Add(value3, value4);
MyClass obj = temp;

Because of the temp variable, if any of the Add() calls generate an exception, the named variable ( obj in this case) is never actually assigned. Interestingly, this also means that if MyClass were to implement IDisposable , then Dispose() would not get called on the constructed object when one of the Add() methods generates an error (I tested this to be sure).

Why require IEnumerable ? Because that interface differentiates classes with Add for collections and classes with Add for calculations.

http://blogs.msdn.com/b/madst/archive/2006/10/10/what-is-a-collection_3f00_.aspx

[when you analyze classes with Add ] you realize that there are essentially two fundamentally different meanings of the name “Add”:

a) Insert the argument into a collection, or

b) Return the arithmetic sum of the argument and the receiver

Also note that if your collection class implements IDisposable , then you should not use collection initializers if there is any chance that Add() will throw an exception or if any of the expressions being fed to Add() can throw an exception.

https://connect.microsoft.com/VisualStudio/feedback/details/654186/collection-initializers-called-on-collections-that-implement-idisposable-need-to-call-dispose-in-case-of-failure#

How about a variable constructor:

public class MyClass
{
    public MyClass() {}
    public MyClass(params object[] list) { ... }
}

Isn't the default good enough ?

new MyClass {
   MyCol = {Value1, Value2, ... },
};

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