개체 및 컬렉션 이니셜라이저(C# 프로그래밍 가이드)Object and Collection Initializers (C# Programming Guide)

개체 이니셜라이저를 사용하면 명시적으로 생성자를 호출한 다음 할당문 줄을 추가하지 않고도 생성 시 개체의 모든 액세스 가능한 필드나 속성에 값을 할당할 수 있습니다.Object initializers let you assign values to any accessible fields or properties of an object at creation time without having to invoke a constructor followed by lines of assignment statements. 개체 이니셜라이저 구문을 사용하면 생성자의 인수를 지정하거나 인수(및 괄호 구문)를 생략할 수 있습니다.The object initializer syntax enables you to specify arguments for a constructor or omit the arguments (and parentheses syntax). 다음 예제는 명명된 형식인 Cat의 개체 이니셜라이저를 사용하는 방법과 기본 생성자를 호출하는 방법을 보여 줍니다.The following example shows how to use an object initializer with a named type, Cat and how to invoke the default constructor. Cat 클래스의 자동 구현된 속성 사용을 확인합니다.Note the use of auto-implemented properties in the Cat class. 자세한 내용은 자동으로 구현된 속성을 참조하세요.For more information, see Auto-Implemented Properties.

class Cat
{
    // Auto-implemented properties.
    public int Age { get; set; }
    public string Name { get; set; }
}
Cat cat = new Cat { Age = 10, Name = "Fluffy" };

개체 이니셜라이저 구문을 사용하여 인스턴스를 만들 수 있으며, 만들고 나면 새로 만든 개체와 할당된 해당 속성이 할당의 변수에 할당됩니다.The object initializers syntax allows you to create an instance, and after that it assigns the newly created object, with its assigned properties, to the variable in the assignment.

익명 형식의 개체 이니셜라이저Object Initializers with anonymous types

개체 이니셜라이저는 모든 컨텍스트에서 사용할 수 있지만 특히 LINQLINQ 쿼리 식에 유용합니다.Although object initializers can be used in any context, they are especially useful in LINQLINQ query expressions. 쿼리 식은 무명 형식을 자주 사용합니다. 이 형식은 다음 선언에 표시된 바와 같이 개체 이니셜라이저를 사용하는 경우에만 초기화될 수 있습니다.Query expressions make frequent use of anonymous types, which can only be initialized by using an object initializer, as shown in the following declaration.

var pet = new { Age = 10, Name = "Fluffy" };  

무명 형식을 사용하면 LINQLINQ 쿼리 식의 select 절에서 원래 시퀀스의 개체를 값과 모양이 원본과 다를 수 있는 개체로 변환할 수 있습니다.Anonymous types enable the select clause in a LINQLINQ query expression to transform objects of the original sequence into objects whose value and shape may differ from the original. 이 기능은 각 개체의 일부 정보만 시퀀스에 저장하려는 경우에 유용합니다.This is useful if you want to store only a part of the information from each object in a sequence. 다음 예제에서 제품 개체(p)는 많은 필드와 메서드를 포함하며, 제품 이름과 단위 가격이 들어 있는 개체 시퀀스만 만들려 한다고 가정합니다.In the following example, assume that a product object (p) contains many fields and methods, and that you are only interested in creating a sequence of objects that contain the product name and the unit price.

var productInfos =
    from p in products
    select new { p.ProductName, p.UnitPrice };

이 쿼리를 실행하면 다음 예제와 같이 productInfos 문에서 액세스할 수 있는 개체 시퀀스가 foreach 변수에 포함됩니다.When this query is executed, the productInfos variable will contain a sequence of objects that can be accessed in a foreach statement as shown in this example:

foreach(var p in productInfos){...}  

새 익명 형식의 각 개체에는 원래 개체의 속성이나 필드와 동일한 이름을 받는 두 개의 public 속성이 있습니다.Each object in the new anonymous type has two public properties which receive the same names as the properties or fields in the original object. 익명 형식을 만들 때 필드 이름을 바꿀 수도 있습니다. 다음 예제에서는 UnitPrice 필드의 이름을 Price로 바꿉니다.You can also rename a field when you are creating an anonymous type; the following example renames the UnitPrice field to Price.

select new {p.ProductName, Price = p.UnitPrice};  

nullable 형식의 개체 이니셜라이저Object initializers with nullable types

개체 이니셜라이저에 nullable 구조체를 사용하는 것은 컴파일 시간 오류입니다.It is a compile-time error to use an object initializer with a nullable struct.

컬렉션 이니셜라이저Collection initializers

컬렉션 이니셜라이저를 사용하면 IEnumerable을 구현하고 적절한 시그니처가 있는 Add를 인스턴스 메서드 또는 확장 메서드로 포함하는 컬렉션 형식을 초기화할 때 하나 이상의 요소 이니셜라이저를 지정할 수 있습니다.Collection initializers let you specify one or more element initializers when you initialize a collection type that implements IEnumerable and has Add with the appropriate signature as an instance method or an extension method. 요소 이니셜라이저는 단순한 값, 식 또는 개체 이니셜라이저일 수 있습니다.The element initializers can be a simple value, an expression or an object initializer. 컬렉션 이니셜라이저를 사용하면 소스 코드에서 클래스의 Add 메서드에 대한 호출을 여러 번 지정할 필요가 없습니다. 컴파일러가 호출을 추가합니다.By using a collection initializer you do not have to specify multiple calls to the Add method of the class in your source code; the compiler adds the calls.

다음 예제에서는 두 개의 단순한 컬렉션 이니셜라이저를 보여 줍니다.The following examples shows two simple collection initializers:

List<int> digits = new List<int> { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };  
List<int> digits2 = new List<int> { 0 + 1, 12 % 3, MakeInt() };  

다음 컬렉션 이니셜라이저는 개체 이니셜라이저를 사용하여 앞의 예제에서 정의된 Cat 클래스의 개체를 초기화합니다.The following collection initializer uses object initializers to initialize objects of the Cat class defined in a previous example. 개별 개체 이니셜라이저는 괄호로 묶이고 쉼표로 구분됩니다.Note that the individual object initializers are enclosed in braces and separated by commas.

List<Cat> cats = new List<Cat>
{
    new Cat(){ Name = "Sylvester", Age=8 },
    new Cat(){ Name = "Whiskers", Age=2 },
    new Cat(){ Name = "Sasha", Age=14 }
};

컬렉션의 Add 메서드에서 허용하는 경우 null을 컬렉션 이니셜라이저의 요소로 지정할 수 있습니다.You can specify null as an element in a collection initializer if the collection's Add method allows it.

List<Cat> moreCats = new List<Cat>
{
    new Cat(){ Name = "Furrytail", Age=5 },
    new Cat(){ Name = "Peaches", Age=4 },
    null
};

컬렉션이 인덱싱을 지원하는 경우 인덱싱된 요소를 지정할 수 있습니다.You can specify indexed elements if the collection supports indexing.

var numbers = new Dictionary<int, string> {   
    [7] = "seven",   
    [9] = "nine",   
    [13] = "thirteen"   
};  

예제Examples

다음 예제에서는 개체 및 컬렉션 이니셜라이저의 개념을 결합합니다.The following example combines the concepts of object and collection initializers.

// The following code consolidates examples from the topic.
class ObjInitializers
{
    class Cat
    {
        // Auto-implemented properties.
        public int Age { get; set; }
        public string Name { get; set; }
    }

    static void Main()
    {
        Cat cat = new Cat { Age = 10, Name = "Fluffy" };

        List<Cat> cats = new List<Cat>
        {
            new Cat(){ Name = "Sylvester", Age=8 },
            new Cat(){ Name = "Whiskers", Age=2 },
            new Cat(){ Name = "Sasha", Age=14 }
        };

        List<Cat> moreCats = new List<Cat>
        {
            new Cat(){ Name = "Furrytail", Age=5 },
            new Cat(){ Name = "Peaches", Age=4 },
            null
        };

        // Display results.
        System.Console.WriteLine(cat.Name);

        foreach (Cat c in cats)
            System.Console.WriteLine(c.Name);

        foreach (Cat c in moreCats)
            if (c != null)
                System.Console.WriteLine(c.Name);
            else
                System.Console.WriteLine("List element has null value.");
    }
    // Output:
    //Fluffy
    //Sylvester
    //Whiskers
    //Sasha
    //Furrytail
    //Peaches
    //List element has null value.
}

다음 예제에 표시된, 여러 매개 변수가 있는 Add 메서드를 포함하는 IEnumerable을 구현하는 개체는 Add 메서드의 시그니처에 해당하는 목록의 항목당 여러 요소가 있는 컬렉션 이니셜라이저를 가능하게 합니다.Shown in the following example, an object which implements IEnumerable containing an Add method with multiple parameters allows for collection initializers with multiple elements per item in the list corresponding to the signature of the Add method.

using System;
using System.Collections;
using System.Collections.Generic;

namespace ExampleProject
{
    class FormattedAddresses : IEnumerable<string>
    {
        private List<string> internalList = new List<string>();
        public IEnumerator<string> GetEnumerator() => internalList.GetEnumerator();

        IEnumerator IEnumerable.GetEnumerator() => internalList.GetEnumerator();

        public void Add(string firstname, string lastname, string street, string city, string state, string zipcode) => internalList.Add(
                $@"{firstname} {lastname}
{street}
{city}, {state} {zipcode}"
            );
    }

    class Program
    {
        static void Main(string[] args)
        {
            FormattedAddresses addresses = new FormattedAddresses()
            {
                {"John", "Doe", "123 Street", "Topeka", "KS", "00000" },
                {"Jane", "Smith", "456 Street", "Topeka", "KS", "00000" }
            };

            Console.WriteLine("Address Entries:");

            foreach(string addressEntry in addresses)
            {
                Console.WriteLine("\r\n" + addressEntry);
            }
        }

        /*
         * Prints:
         
            Address Entries:

            John Doe
            123 Street
            Topeka, KS 00000

            Jane Smith
            456 Street
            Topeka, KS 00000
         */
    }
}

다음 예제에 표시된 것처럼 Add 메서드는 params 키워드를 사용하여 가변적인 인수 개수를 사용할 수 있습니다.Add methods can use the params keyword to take a variable number of arguments as shown in the following example. 이 예제에서는 인덱스를 사용하여 컬렉션을 초기화하기 위한 인덱서의 사용자 지정 구현도 보여 줍니다.This example demonstrates the custom implementation of an indexer as well to initialize a collection using indexes.

using System;
using System.Collections;
using System.Collections.Generic;

namespace ExampleProject
{
    class RudimentaryMultiValuedDictionary<TKey, TValue> : IEnumerable<KeyValuePair<TKey, List<TValue>>>
    {
        private Dictionary<TKey, List<TValue>> internalDictionary = new Dictionary<TKey, List<TValue>>();

        public IEnumerator<KeyValuePair<TKey, List<TValue>>> GetEnumerator() => internalDictionary.GetEnumerator();

        IEnumerator IEnumerable.GetEnumerator() => internalDictionary.GetEnumerator();

        public List<TValue> this[TKey key]
        {
            get => internalDictionary[key];
            set => Add(key, value);
        }

        public void Add(TKey key, params TValue[] values) => Add(key, (IEnumerable<TValue>)values);

        public void Add(TKey key, IEnumerable<TValue> values)
        {
            if (!internalDictionary.TryGetValue(key, out List<TValue> storedValues))
                internalDictionary.Add(key, storedValues = new List<TValue>());

            storedValues.AddRange(values);
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            RudimentaryMultiValuedDictionary<string, string> rudimentaryMultiValuedDictionary1
                = new RudimentaryMultiValuedDictionary<string, string>()
                {
                    {"Group1", "Bob", "John", "Mary" },
                    {"Group2", "Eric", "Emily", "Debbie", "Jesse" }
                };
            RudimentaryMultiValuedDictionary<string, string> rudimentaryMultiValuedDictionary2
                = new RudimentaryMultiValuedDictionary<string, string>()
                {
                    ["Group1"] = new List<string>() { "Bob", "John", "Mary" },
                    ["Group2"] = new List<string>() { "Eric", "Emily", "Debbie", "Jesse" }
                };

            Console.WriteLine("Using first multi-valued dictionary created with a collection initializer:");

            foreach(KeyValuePair<string, List<string>> group in rudimentaryMultiValuedDictionary1)
            {
                Console.WriteLine($"\r\nMembers of group {group.Key}: ");

                foreach(string member in group.Value)
                {
                    Console.WriteLine(member);
                }
            }

            Console.WriteLine("\r\nUsing second multi-valued dictionary created with a collection initializer using indexing:");

            foreach (KeyValuePair<string, List<string>> group in rudimentaryMultiValuedDictionary2)
            {
                Console.WriteLine($"\r\nMembers of group {group.Key}: ");

                foreach (string member in group.Value)
                {
                    Console.WriteLine(member);
                }
            }
        }

        /*
         * Prints:
         
            Using first multi-valued dictionary created with a collection initializer:

            Members of group Group1:
            Bob
            John
            Mary

            Members of group Group2:
            Eric
            Emily
            Debbie
            Jesse

            Using second multi-valued dictionary created with a collection initializer using indexing:

            Members of group Group1:
            Bob
            John
            Mary

            Members of group Group2:
            Eric
            Emily
            Debbie
            Jesse
         */
    }
}

참고 항목See Also

C# 프로그래밍 가이드C# Programming Guide
LINQ 쿼리 식LINQ Query Expressions
익명 형식Anonymous Types