달력

5

« 2024/5 »

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
2017. 5. 9. 03:26

C# Programming Guide - Arrays 프로그래밍/C#2017. 5. 9. 03:26



  1. Arrays
  2. Arrays as Objects
  3. Single-Dimensional Arrays
  4. Multidimensional Arrays
  5. Jagged Arrays
  6. Using foreach with Arrays
  7. Passing Arrays as Arguments
  8. Passing Arrays Using ref and out
  9. Implicitly Typed Arrays


https://docs.microsoft.com/en-us/dotnet/articles/csharp/programming-guide/arrays/


Arrays


You can store multiple variables of the same type in an array data structure. You declare an array by specifying the type of its elements.

type[] arrayName;

The following examples create single-dimensional, multidimensional, and jagged arrays:

C#
class LINQQueryExpressions
{
    static void Main()
    {
        
        // Specify the data source.
        int[] scores = new int[] { 97, 92, 81, 60 };

        // Define the query expression.
        IEnumerable<int> scoreQuery =
            from score in scores
            where score > 80
            select score;

        // Execute the query.
        foreach (int i in scoreQuery)
        {
            Console.Write(i + " ");
        }            
    }
}
// Output: 97 92 81

Array Overview

An array has the following properties:

  • An array can be Single-DimensionalMultidimensional or Jagged.

  • The number of dimensions and the length of each dimension are established when the array instance is created. These values can't be changed during the lifetime of the instance.

  • The default values of numeric array elements are set to zero, and reference elements are set to null.

  • A jagged array is an array of arrays, and therefore its elements are reference types and are initialized to null.

  • Arrays are zero indexed: an array with n elements is indexed from 0 to n-1.

  • Array elements can be of any type, including an array type.

  • Array types are reference types derived from the abstract base type Array. Since this type implements IEnumerable and IEnumerable<T>, you can use foreach iteration on all arrays in C#.






Arrays as Objects


In C#, arrays are actually objects, and not just addressable regions of contiguous memory as in C and C++. Arrayis the abstract base type of all array types. You can use the properties, and other class members, that Array has. An example of this would be using the Length property to get the length of an array. The following code assigns the length of the numbers array, which is 5, to a variable called lengthOfNumbers:

C#
int[] numbers = { 1, 2, 3, 4, 5 };
int lengthOfNumbers = numbers.Length;

The Array class provides many other useful methods and properties for sorting, searching, and copying arrays.

Example

This example uses the Rank property to display the number of dimensions of an array.

C#
class TestArraysClass
{
    static void Main()
    {
        // Declare and initialize an array:
        int[,] theArray = new int[5, 10];
        System.Console.WriteLine("The array has {0} dimensions.", theArray.Rank);
    }
}
// Output: The array has 2 dimensions.








You can declare a single-dimensional array of five integers as shown in the following example:

C#
int[] array = new int[5];

This array contains the elements from array[0] to array[4]. The new operator is used to create the array and initialize the array elements to their default values. In this example, all the array elements are initialized to zero.

An array that stores string elements can be declared in the same way. For example:

C#
string[] stringArray = new string[6];

Array Initialization

It is possible to initialize an array upon declaration, in which case, the rank specifier is not needed because it is already supplied by the number of elements in the initialization list. For example:

C#
int[] array1 = new int[] { 1, 3, 5, 7, 9 };

A string array can be initialized in the same way. The following is a declaration of a string array where each array element is initialized by a name of a day:

C#
string[] weekDays = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };

When you initialize an array upon declaration, you can use the following shortcuts:

C#
int[] array2 = { 1, 3, 5, 7, 9 };
string[] weekDays2 = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };

It is possible to declare an array variable without initialization, but you must use the new operator when you assign an array to this variable. For example:

C#
int[] array3;
array3 = new int[] { 1, 3, 5, 7, 9 };   // OK
//array3 = {1, 3, 5, 7, 9};   // Error

C# 3.0 introduces implicitly typed arrays. For more information, see Implicitly Typed Arrays.

Value Type and Reference Type Arrays

Consider the following array declaration:

C#
SomeType[] array4 = new SomeType[10];

The result of this statement depends on whether SomeType is a value type or a reference type. If it is a value type, the statement creates an array of 10 elements, each of which has the type SomeType. If SomeType is a reference type, the statement creates an array of 10 elements, each of which is initialized to a null reference.

For more information about value types and reference types, see Types.






Multidimensional Arrays


Arrays can have more than one dimension. For example, the following declaration creates a two-dimensional array of four rows and two columns.

C#
int[,] array = new int[4, 2];

The following declaration creates an array of three dimensions, 4, 2, and 3.

C#
int[, ,] array1 = new int[4, 2, 3];

Array Initialization

You can initialize the array upon declaration, as is shown in the following example.

C#
// Two-dimensional array.
int[,] array2D = new int[,] { { 1, 2 }, { 3, 4 }, { 5, 6 }, { 7, 8 } };
// The same array with dimensions specified.
int[,] array2Da = new int[4, 2] { { 1, 2 }, { 3, 4 }, { 5, 6 }, { 7, 8 } };
// A similar array with string elements.
string[,] array2Db = new string[3, 2] { { "one", "two" }, { "three", "four" },
                                        { "five", "six" } };

// Three-dimensional array.
int[, ,] array3D = new int[,,] { { { 1, 2, 3 }, { 4, 5, 6 } }, 
                                 { { 7, 8, 9 }, { 10, 11, 12 } } };
// The same array with dimensions specified.
int[, ,] array3Da = new int[2, 2, 3] { { { 1, 2, 3 }, { 4, 5, 6 } }, 
                                       { { 7, 8, 9 }, { 10, 11, 12 } } };

// Accessing array elements.
System.Console.WriteLine(array2D[0, 0]);
System.Console.WriteLine(array2D[0, 1]);
System.Console.WriteLine(array2D[1, 0]);
System.Console.WriteLine(array2D[1, 1]);
System.Console.WriteLine(array2D[3, 0]);
System.Console.WriteLine(array2Db[1, 0]);
System.Console.WriteLine(array3Da[1, 0, 1]);
System.Console.WriteLine(array3D[1, 1, 2]);

// Getting the total count of elements or the length of a given dimension.
var allLength = array3D.Length;
var total = 1;
for (int i = 0; i < array3D.Rank; i++) {
    total *= array3D.GetLength(i);
}
System.Console.WriteLine("{0} equals {1}", allLength, total);

// Output:
// 1
// 2
// 3
// 4
// 7
// three
// 8
// 12
// 12 equals 12

You also can initialize the array without specifying the rank.

C#
int[,] array4 = { { 1, 2 }, { 3, 4 }, { 5, 6 }, { 7, 8 } };

If you choose to declare an array variable without initialization, you must use the new operator to assign an array to the variable. The use of new is shown in the following example.

C#
int[,] array5;
array5 = new int[,] { { 1, 2 }, { 3, 4 }, { 5, 6 }, { 7, 8 } };   // OK
//array5 = {{1,2}, {3,4}, {5,6}, {7,8}};   // Error

The following example assigns a value to a particular array element.

C#
array5[2, 1] = 25;

Similarly, the following example gets the value of a particular array element and assigns it to variable elementValue.

C#
int elementValue = array5[2, 1];

The following code example initializes the array elements to default values (except for jagged arrays).

C#
int[,] array6 = new int[10, 10];






Jagged Arrays


A jagged array is an array whose elements are arrays. The elements of a jagged array can be of different dimensions and sizes. A jagged array is sometimes called an "array of arrays." The following examples show how to declare, initialize, and access jagged arrays.

The following is a declaration of a single-dimensional array that has three elements, each of which is a single-dimensional array of integers:

C#
int[][] jaggedArray = new int[3][];

Before you can use jaggedArray, its elements must be initialized. You can initialize the elements like this:

C#
jaggedArray[0] = new int[5];
jaggedArray[1] = new int[4];
jaggedArray[2] = new int[2];

Each of the elements is a single-dimensional array of integers. The first element is an array of 5 integers, the second is an array of 4 integers, and the third is an array of 2 integers.

It is also possible to use initializers to fill the array elements with values, in which case you do not need the array size. For example:

C#
jaggedArray[0] = new int[] { 1, 3, 5, 7, 9 };
jaggedArray[1] = new int[] { 0, 2, 4, 6 };
jaggedArray[2] = new int[] { 11, 22 };

You can also initialize the array upon declaration like this:

C#
    int[][] jaggedArray2 = new int[][] 
{
    new int[] {1,3,5,7,9},
    new int[] {0,2,4,6},
    new int[] {11,22}
};

You can use the following shorthand form. Notice that you cannot omit the new operator from the elements initialization because there is no default initialization for the elements:

C#
    int[][] jaggedArray3 = 
{
    new int[] {1,3,5,7,9},
    new int[] {0,2,4,6},
    new int[] {11,22}
};

A jagged array is an array of arrays, and therefore its elements are reference types and are initialized to null.

You can access individual array elements like these examples:

C#
// Assign 77 to the second element ([1]) of the first array ([0]):
jaggedArray3[0][1] = 77;

// Assign 88 to the second element ([1]) of the third array ([2]):
jaggedArray3[2][1] = 88;

It is possible to mix jagged and multidimensional arrays. The following is a declaration and initialization of a single-dimensional jagged array that contains three two-dimensional array elements of different sizes. For more information about two-dimensional arrays, see Multidimensional Arrays.

C#
int[][,] jaggedArray4 = new int[3][,] 
{
    new int[,] { {1,3}, {5,7} },
    new int[,] { {0,2}, {4,6}, {8,10} },
    new int[,] { {11,22}, {99,88}, {0,9} } 
};

You can access individual elements as shown in this example, which displays the value of the element [1,0] of the first array (value 5):

C#
System.Console.Write("{0}", jaggedArray4[0][1, 0]);

The method Length returns the number of arrays contained in the jagged array. For example, assuming you have declared the previous array, this line:

C#
System.Console.WriteLine(jaggedArray4.Length);

returns a value of 3.

Example

This example builds an array whose elements are themselves arrays. Each one of the array elements has a different size.

C#
class ArrayTest
{
    static void Main()
    {
        // Declare the array of two elements:
        int[][] arr = new int[2][];

        // Initialize the elements:
        arr[0] = new int[5] { 1, 3, 5, 7, 9 };
        arr[1] = new int[4] { 2, 4, 6, 8 };

        // Display the array elements:
        for (int i = 0; i < arr.Length; i++)
        {
            System.Console.Write("Element({0}): ", i);

            for (int j = 0; j < arr[i].Length; j++)
            {
                System.Console.Write("{0}{1}", arr[i][j], j == (arr[i].Length - 1) ? "" : " ");
            }
            System.Console.WriteLine();            
        }
        // Keep the console window open in debug mode.
        System.Console.WriteLine("Press any key to exit.");
        System.Console.ReadKey();
    }
}
/* Output:
    Element(0): 1 3 5 7 9
    Element(1): 2 4 6 8
*/






Using foreach with Arrays


C# also provides the foreach statement. This statement provides a simple, clean way to iterate through the elements of an array or any enumerable collection. The foreach statement processes elements in the order returned by the array or collection type’s enumerator, which is usually from the 0th element to the last. For example, the following code creates an array called numbers and iterates through it with the foreach statement:

C#
int[] numbers = { 4, 5, 6, 1, 2, 3, -2, -1, 0 };
foreach (int i in numbers)
{
    System.Console.Write("{0} ", i);
}
// Output: 4 5 6 1 2 3 -2 -1 0

With multidimensional arrays, you can use the same method to iterate through the elements, for example:

C#
int[,] numbers2D = new int[3, 2] { { 9, 99 }, { 3, 33 }, { 5, 55 } };
// Or use the short form:
// int[,] numbers2D = { { 9, 99 }, { 3, 33 }, { 5, 55 } };

foreach (int i in numbers2D)
{
    System.Console.Write("{0} ", i);
}
// Output: 9 99 3 33 5 55

However, with multidimensional arrays, using a nested for loop gives you more control over the array elements.






Passing Arrays as Arguments


Arrays can be passed as arguments to method parameters. Because arrays are reference types, the method can change the value of the elements.

Passing Single-Dimensional Arrays As Arguments

You can pass an initialized single-dimensional array to a method. For example, the following statement sends an array to a print method.

C#
int[] theArray = { 1, 3, 5, 7, 9 };
PrintArray(theArray);

The following code shows a partial implementation of the print method.

C#
void PrintArray(int[] arr)
{
    // Method code.
}

You can initialize and pass a new array in one step, as is shown in the following example.

C#
PrintArray(new int[] { 1, 3, 5, 7, 9 });

Example

Description

In the following example, an array of strings is initialized and passed as an argument to a PrintArray method for strings. The method displays the elements of the array. Next, methods ChangeArray and ChangeArrayElement are called to demonstrate that sending an array argument by value does not prevent changes to the array elements.

Code

C#
class ArrayClass
{
    static void PrintArray(string[] arr)
    {
        for (int i = 0; i < arr.Length; i++)
        {
            System.Console.Write(arr[i] + "{0}", i < arr.Length - 1 ? " " : "");
        }
        System.Console.WriteLine();
    }

    static void ChangeArray(string[] arr)
    {
        // The following attempt to reverse the array does not persist when
        // the method returns, because arr is a value parameter.
        arr = (arr.Reverse()).ToArray();
        // The following statement displays Sat as the first element in the array.
        System.Console.WriteLine("arr[0] is {0} in ChangeArray.", arr[0]);
    }

    static void ChangeArrayElements(string[] arr)
    {
        // The following assignments change the value of individual array 
        // elements. 
        arr[0] = "Sat";
        arr[1] = "Fri";
        arr[2] = "Thu";
        // The following statement again displays Sat as the first element
        // in the array arr, inside the called method.
        System.Console.WriteLine("arr[0] is {0} in ChangeArrayElements.", arr[0]);
    }

    static void Main()
    {
        // Declare and initialize an array.
        string[] weekDays = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };

        // Pass the array as an argument to PrintArray.
        PrintArray(weekDays);

        // ChangeArray tries to change the array by assigning something new
        // to the array in the method. 
        ChangeArray(weekDays);

        // Print the array again, to verify that it has not been changed.
        System.Console.WriteLine("Array weekDays after the call to ChangeArray:");
        PrintArray(weekDays);
        System.Console.WriteLine();

        // ChangeArrayElements assigns new values to individual array
        // elements.
        ChangeArrayElements(weekDays);

        // The changes to individual elements persist after the method returns.
        // Print the array, to verify that it has been changed.
        System.Console.WriteLine("Array weekDays after the call to ChangeArrayElements:");
        PrintArray(weekDays);
    }
}
// Output: 
// Sun Mon Tue Wed Thu Fri Sat
// arr[0] is Sat in ChangeArray.
// Array weekDays after the call to ChangeArray:
// Sun Mon Tue Wed Thu Fri Sat
// 
// arr[0] is Sat in ChangeArrayElements.
// Array weekDays after the call to ChangeArrayElements:
// Sat Fri Thu Wed Thu Fri Sat

Passing Multidimensional Arrays As Arguments

You pass an initialized multidimensional array to a method in the same way that you pass a one-dimensional array.

C#
int[,] theArray = { { 1, 2 }, { 2, 3 }, { 3, 4 } };
Print2DArray(theArray);

The following code shows a partial declaration of a print method that accepts a two-dimensional array as its argument.

C#
void Print2DArray(int[,] arr)
{
    // Method code.
}

You can initialize and pass a new array in one step, as is shown in the following example.

C#
Print2DArray(new int[,] { { 1, 2 }, { 3, 4 }, { 5, 6 }, { 7, 8 } });

Example

Description

In the following example, a two-dimensional array of integers is initialized and passed to the Print2DArray method. The method displays the elements of the array.

Code

C#
class ArrayClass2D
{
    static void Print2DArray(int[,] arr)
    {
        // Display the array elements.
        for (int i = 0; i < arr.GetLength(0); i++)
        {
            for (int j = 0; j < arr.GetLength(1); j++)
            {
                System.Console.WriteLine("Element({0},{1})={2}", i, j, arr[i, j]);
            }
        }
    }
    static void Main()
    {
        // Pass the array as an argument.
        Print2DArray(new int[,] { { 1, 2 }, { 3, 4 }, { 5, 6 }, { 7, 8 } });

        // Keep the console window open in debug mode.
        System.Console.WriteLine("Press any key to exit.");
        System.Console.ReadKey();
    }
}
    /* Output:
        Element(0,0)=1
        Element(0,1)=2
        Element(1,0)=3
        Element(1,1)=4
        Element(2,0)=5
        Element(2,1)=6
        Element(3,0)=7
        Element(3,1)=8
    */






Passing Arrays Using ref and out


Like all out parameters, an out parameter of an array type must be assigned before it is used; that is, it must be assigned by the callee. For example:

C#
static void TestMethod1(out int[] arr)
{
    arr = new int[10];   // definite assignment of arr
}

Like all ref parameters, a ref parameter of an array type must be definitely assigned by the caller. Therefore, there is no need to be definitely assigned by the callee. A ref parameter of an array type may be altered as a result of the call. For example, the array can be assigned the null value or can be initialized to a different array. For example:

C#
static void TestMethod2(ref int[] arr)
{
    arr = new int[10];   // arr initialized to a different array
}

The following two examples demonstrate the difference between out and ref when used in passing arrays to methods.

Example

In this example, the array theArray is declared in the caller (the Main method), and initialized in the FillArray method. Then, the array elements are returned to the caller and displayed.

C#
class TestOut
{
    static void FillArray(out int[] arr)
    {
        // Initialize the array:
        arr = new int[5] { 1, 2, 3, 4, 5 };
    }

    static void Main()
    {
        int[] theArray; // Initialization is not required

        // Pass the array to the callee using out:
        FillArray(out theArray);

        // Display the array elements:
        System.Console.WriteLine("Array elements are:");
        for (int i = 0; i < theArray.Length; i++)
        {
            System.Console.Write(theArray[i] + " ");
        }

        // Keep the console window open in debug mode.
        System.Console.WriteLine("Press any key to exit.");
        System.Console.ReadKey();
    }
}
    /* Output:
        Array elements are:
        1 2 3 4 5        
    */

Example

In this example, the array theArray is initialized in the caller (the Main method), and passed to the FillArray method by using the ref parameter. Some of the array elements are updated in the FillArray method. Then, the array elements are returned to the caller and displayed.

C#
class TestRef
{
    static void FillArray(ref int[] arr)
    {
        // Create the array on demand:
        if (arr == null)
        {
            arr = new int[10];
        }
        // Fill the array:
        arr[0] = 1111;
        arr[4] = 5555;
    }

    static void Main()
    {
        // Initialize the array:
        int[] theArray = { 1, 2, 3, 4, 5 };

        // Pass the array using ref:
        FillArray(ref theArray);

        // Display the updated array:
        System.Console.WriteLine("Array elements are:");
        for (int i = 0; i < theArray.Length; i++)
        {
            System.Console.Write(theArray[i] + " ");
        }

        // Keep the console window open in debug mode.
        System.Console.WriteLine("Press any key to exit.");
        System.Console.ReadKey();
    }
}
    /* Output:
        Array elements are:
        1111 2 3 4 5555
    */






Implicitly Typed Arrays


You can create an implicitly-typed array in which the type of the array instance is inferred from the elements specified in the array initializer. The rules for any implicitly-typed variable also apply to implicitly-typed arrays. For more information, see Implicitly Typed Local Variables.

Implicitly-typed arrays are usually used in query expressions together with anonymous types and object and collection initializers.

The following examples show how to create an implicitly-typed array:

C#
class ImplicitlyTypedArraySample
{
    static void Main()
    {
        var a = new[] { 1, 10, 100, 1000 }; // int[]
        var b = new[] { "hello", null, "world" }; // string[]

        // single-dimension jagged array
        var c = new[]   
{  
    new[]{1,2,3,4},
    new[]{5,6,7,8}
};

        // jagged array of strings
        var d = new[]   
{
    new[]{"Luca", "Mads", "Luke", "Dinesh"},
    new[]{"Karen", "Suma", "Frances"}
};
    }
}

In the previous example, notice that with implicitly-typed arrays, no square brackets are used on the left side of the initialization statement. Note also that jagged arrays are initialized by using new [] just like single-dimension arrays.

Implicitly-typed Arrays in Object Initializers

When you create an anonymous type that contains an array, the array must be implicitly typed in the type's object initializer. In the following example, contacts is an implicitly-typed array of anonymous types, each of which contains an array named PhoneNumbers. Note that the var keyword is not used inside the object initializers.

C#
        var contacts = new[] 
{
    new {
            Name = " Eugene Zabokritski",
            PhoneNumbers = new[] { "206-555-0108", "425-555-0001" }
        },
    new {
            Name = " Hanying Feng",
            PhoneNumbers = new[] { "650-555-0199" }
        }
};




:
Posted by 지훈2
2017. 5. 8. 17:33

Tuple Class 프로그래밍/C#2017. 5. 8. 17:33



https://msdn.microsoft.com/en-us/library/system.tuple(v=vs.110).aspx


Tuple Class


Provides static methods for creating tuple objects.

To browse the .NET Framework source code for this type, see the Reference Source.

Namespace:   System
Assembly:  mscorlib (in mscorlib.dll)


Syntax

public static class Tuple

Remarks

System_CAPS_noteNote

To view the .NET Framework source code for this type, see the Reference Source. You can browse through the source code online, download the reference for offline viewing, and step through the sources (including patches and updates) during debugging; see instructions.

A tuple is a data structure that has a specific number and sequence of elements. An example of a tuple is a data structure with three elements (known as a 3-tuple or triple) that is used to store an identifier such as a person's name in the first element, a year in the second element, and the person's income for that year in the third element. The .NET Framework directly supports tuples with one to seven elements. In addition, you can create tuples of eight or more elements by nesting tuple objects in the Rest property of a Tuple<T1, T2, T3, T4, T5, T6, T7, TRest> object.

Tuples are commonly used in four ways:

  • To represent a single set of data. For example, a tuple can represent a database record, and its components can represent individual fields of the record.

  • To provide easy access to, and manipulation of, a data set.

  • To return multiple values from a method without using out parameters (in C#) or ByRef parameters (in Visual Basic).

  • To pass multiple values to a method through a single parameter. For example, the Thread.Start(Object) method has a single parameter that lets you supply one value to the method that the thread executes at startup time. If you supply a Tuple<T1, T2, T3> object as the method argument, you can supply the thread’s startup routine with three items of data.

The Tuple class does not itself represent a tuple. Instead, it is a class that provides static methods for creating instances of the tuple types that are supported by the .NET Framework. It provides helper methods that you can call to instantiate tuple objects without having to explicitly specify the type of each tuple component.

Although you can create an instance of a tuple class by calling its class constructor, the code to do so can be cumbersome. The following example uses a class constructor to create a 7-tuple or septuple that contains population data for New York City for each census from 1950 through 2000.

// Create a 7-tuple.
var population = new Tuple<string, int, int, int, int, int, int>(
                           "New York", 7891957, 7781984, 
                           7894862, 7071639, 7322564, 8008278);
// Display the first and last elements.
Console.WriteLine("Population of {0} in 2000: {1:N0}",
                  population.Item1, population.Item7);
// The example displays the following output:
//       Population of New York in 2000: 8,008,278

Creating the same tuple object by using a helper method is more straightforward, as the following example shows.

// Create a 7-tuple.
var population = Tuple.Create("New York", 7891957, 7781984, 7894862, 7071639, 7322564, 8008278);
// Display the first and last elements.
Console.WriteLine("Population of {0} in 2000: {1:N0}",
                  population.Item1, population.Item7);
// The example displays the following output:
//       Population of New York in 2000: 8,008,278

The Create helper methods directly support the creation of tuple objects that have from one to eight components (that is, singletons through octuples). Although there is no practical limit to the number of components a tuple may have, helper methods are not available to create a tuple with nine or more components. To create such a tuple, you must call the Tuple<T1, T2, T3, T4, T5, T6, T7, TRest>.Tuple<T1, T2, T3, T4, T5, T6, T7, TRest> constructor.

System_CAPS_noteNote

For additional information and examples that use tuples, see the documentation for the individual tuple types in the .NET Framework. These are listed in the See Also section at the end of this topic.

Examples

The following example creates an 8-tuple (octuple) that contains prime numbers that are less than 20.

var primes = Tuple.Create(2, 3, 5, 7, 11, 13, 17, 19);
Console.WriteLine("Prime numbers less than 20: " + 
                  "{0}, {1}, {2}, {3}, {4}, {5}, {6}, and {7}",
                  primes.Item1, primes.Item2, primes.Item3, 
                  primes.Item4, primes.Item5, primes.Item6,
                  primes.Item7, primes.Rest.Item1);
// The example displays the following output:
//    Prime numbers less than 20: 2, 3, 5, 7, 11, 13, 17, and 19






:
Posted by 지훈2




https://msdn.microsoft.com/en-us/library/hh156531(v=vs.110).aspx


Memory Management and Garbage Collection in the .NET Framework


This section of the documentation provides information about managing memory in the .NET Framework.

Cleaning Up Unmanaged Resources
Describes how to properly manage and clean up unmanaged resources..

Garbage Collection
Provides information about the .NET Framework garbage collector.










IDisposable Interface


Provides a mechanism for releasing unmanaged resources.

To browse the .NET Framework source code for this type, see the Reference Source.

Namespace:   System
Assembly:  mscorlib (in mscorlib.dll)

Syntax

[ComVisibleAttribute(true)]
public interface IDisposable

Methods

NameDescription
System_CAPS_pubmethodDispose()

Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.

Remarks

System_CAPS_noteNote

To view the .NET Framework source code for this type, see the Reference Source. You can browse through the source code online, download the reference for offline viewing, and step through the sources (including patches and updates) during debugging; see instructions.

The primary use of this interface is to release unmanaged resources. The garbage collector automatically releases the memory allocated to a managed object when that object is no longer used. However, it is not possible to predict when garbage collection will occur. Furthermore, the garbage collector has no knowledge of unmanaged resources such as window handles, or open files and streams.

Use the Dispose method of this interface to explicitly release unmanaged resources in conjunction with the garbage collector. The consumer of an object can call this method when the object is no longer needed.

System_CAPS_warningWarning

It is a breaking change to add the IDisposable interface to an existing class. Because pre-existing consumers of your type cannot call Dispose, you cannot be certain that unmanaged resources held by your type will be released.

Because the IDisposable.Dispose implementation is called by the consumer of a type when the resources owned by an instance are no longer needed, you should either wrap the managed object in a SafeHandle (the recommended alternative), or you should override Object.Finalize to free unmanaged resources in the event that the consumer forgets to call Dispose.

System_CAPS_importantImportant

In the .NET Framework, the C++ compiler supports deterministic disposal of resources and does not allow direct implementation of the Dispose method.

For a detailed discussion about how this interface and the Object.Finalize method are used, see the Garbage Collection and Implementing a Dispose Method topics.

Using an object that implements IDisposable

Implement IDisposable only if you are using unmanaged resources directly. If your app simply uses an object that implements IDisposable, don't provide an IDisposable implementation. Instead, you should call the object's IDisposable.Dispose implementation when you are finished using it. Depending on your programming language, you can do this in one of two ways:

  • By using a language construct such as the using statement in C# and Visual Basic.

  • By wrapping the call to the IDisposable.Dispose implementation in a try/catch block.

System_CAPS_noteNote

Documentation for types that implement IDisposable note that fact and include a reminder to call its Dispose implementation.

The C# and Visual Basic Using statement

If your language supports a construct such as the using statement in C# and the Using statement in Visual Basic, you can use it instead of explicitly calling IDisposable.Dispose yourself. The following example uses this approach in defining a WordCount class that preserves information about a file and the number of words in it.

using System;
using System.IO;
using System.Text.RegularExpressions;

public class WordCount
{
   private String filename = String.Empty;
   private int nWords = 0;
   private String pattern = @"\b\w+\b"; 

   public WordCount(string filename)
   {
      if (! File.Exists(filename))
         throw new FileNotFoundException("The file does not exist.");

      this.filename = filename;
      string txt = String.Empty;
      using (StreamReader sr = new StreamReader(filename)) {
         txt = sr.ReadToEnd();
      }
      nWords = Regex.Matches(txt, pattern).Count;
   }

   public string FullName
   { get { return filename; } }

   public string Name
   { get { return Path.GetFileName(filename); } }

   public int Count 
   { get { return nWords; } }
}   

The using statement is actually a syntactic convenience. At compile time, the language compiler implements the intermediate language (IL) for a try/catch block.

For more information about the using statement, see the Using Statement (Visual Basic) or using Statement (C# Reference) topics.

The Try/Catch block

If your programming language does not support a construct like the using statement in C# or Visual Basic, or if you prefer not to use it, you can call the IDisposable.Dispose implementation from the finally block of a try/catch statement. The following example replaces the using block in the previous example with a try/catch/finally block.

using System;
using System.IO;
using System.Text.RegularExpressions;

public class WordCount
{
   private String filename = String.Empty;
   private int nWords = 0;
   private String pattern = @"\b\w+\b"; 

   public WordCount(string filename)
   {
      if (! File.Exists(filename))
         throw new FileNotFoundException("The file does not exist.");

      this.filename = filename;
      string txt = String.Empty;
      StreamReader sr = null;
      try {
         sr = new StreamReader(filename);
         txt = sr.ReadToEnd();
      }
      finally {
         if (sr != null) sr.Dispose();     
      }
      nWords = Regex.Matches(txt, pattern).Count;
   }

   public string FullName
   { get { return filename; } }

   public string Name
   { get { return Path.GetFileName(filename); } }

   public int Count 
   { get { return nWords; } }
}   

For more information about the try/finally pattern, see Try...Catch...Finally Statement (Visual Basic)try-finally (C# Reference), or try-finally Statement (C).

Implementing IDisposable

You should implement IDisposable only if your type uses unmanaged resources directly. The consumers of your type can call your IDisposable.Dispose implementation to free resources when the instance is no longer needed. To handle cases in which they fail to call Dispose, you should either use a class derived from SafeHandle to wrap the unmanaged resources, or you should override the Object.Finalize method for a reference type. In either case, you use the Dispose method to perform whatever cleanup is necessary after using the unmanaged resources, such as freeing, releasing, or resetting the unmanaged resources.

System_CAPS_importantImportant

If you are defining a base class that uses unmanaged resources and that either has, or is likely to have, subclasses that should be disposed, you should implement the IDisposable.Dispose method and provide a second overload of Dispose, as discussed in the next section.

IDisposable and the inheritance hierarchy

A base class with subclasses that should be disposable must implement IDisposable as follows. You should use this pattern whenever you implement IDisposable on any type that isn't sealed (NotInheritable in Visual Basic).

  • It should provide one public, non-virtual Dispose() method and a protected virtual Dispose(Boolean disposing) method.

  • The Dispose() method must call Dispose(true) and should suppress finalization for performance.

  • The base type should not include any finalizers.

The following code fragment reflects the dispose pattern for base classes. It assumes that your type does not override the Object.Finalize method.

using Microsoft.Win32.SafeHandles;
using System;
using System.Runtime.InteropServices;

class BaseClass : IDisposable
{
   // Flag: Has Dispose already been called?
   bool disposed = false;
   // Instantiate a SafeHandle instance.
   SafeHandle handle = new SafeFileHandle(IntPtr.Zero, true);

   // Public implementation of Dispose pattern callable by consumers.
   public void Dispose()
   { 
      Dispose(true);
      GC.SuppressFinalize(this);           
   }

   // Protected implementation of Dispose pattern.
   protected virtual void Dispose(bool disposing)
   {
      if (disposed)
         return; 

      if (disposing) {
         handle.Dispose();
         // Free any other managed objects here.
         //
      }

      // Free any unmanaged objects here.
      //
      disposed = true;
   }
}

If you do override the Object.Finalize method, your class should implement the following pattern.

using System;

class BaseClass : IDisposable
{
   // Flag: Has Dispose already been called?
   bool disposed = false;

   // Public implementation of Dispose pattern callable by consumers.
   public void Dispose()
   { 
      Dispose(true);
      GC.SuppressFinalize(this);           
   }

   // Protected implementation of Dispose pattern.
   protected virtual void Dispose(bool disposing)
   {
      if (disposed)
         return; 

      if (disposing) {
         // Free any other managed objects here.
         //
      }

      // Free any unmanaged objects here.
      //
      disposed = true;
   }

   ~BaseClass()
   {
      Dispose(false);
   }
}

Subclasses should implement the disposable pattern as follows:

  • They must override Dispose(Boolean) and call the base class Dispose(Boolean) implementation.

  • They can provide a finalizer if needed. The finalizer must call Dispose(false).

Note that derived classes do not themselves implement the IDisposable interface and do not include a parameterless Dispose method. They only override the base class Dispose(Boolean) method.

The following code fragment reflects the dispose pattern for derived classes. It assumes that your type does not override the Object.Finalize method.

using Microsoft.Win32.SafeHandles;
using System;
using System.Runtime.InteropServices;

class DerivedClass : BaseClass
{
   // Flag: Has Dispose already been called?
   bool disposed = false;
   // Instantiate a SafeHandle instance.
   SafeHandle handle = new SafeFileHandle(IntPtr.Zero, true);

   // Protected implementation of Dispose pattern.
   protected override void Dispose(bool disposing)
   {
      if (disposed)
         return; 

      if (disposing) {
         handle.Dispose();
         // Free any other managed objects here.
         //
      }

      // Free any unmanaged objects here.
      //

      disposed = true;
      // Call base class implementation.
      base.Dispose(disposing);
   }
}

Examples

The following example demonstrates how to create a resource class that implements the IDisposable interface.

using System;
using System.ComponentModel;

// The following example demonstrates how to create
// a resource class that implements the IDisposable interface
// and the IDisposable.Dispose method.

public class DisposeExample
{
    // A base class that implements IDisposable.
    // By implementing IDisposable, you are announcing that
    // instances of this type allocate scarce resources.
    public class MyResource: IDisposable
    {
        // Pointer to an external unmanaged resource.
        private IntPtr handle;
        // Other managed resource this class uses.
        private Component component = new Component();
        // Track whether Dispose has been called.
        private bool disposed = false;

        // The class constructor.
        public MyResource(IntPtr handle)
        {
            this.handle = handle;
        }

        // Implement IDisposable.
        // Do not make this method virtual.
        // A derived class should not be able to override this method.
        public void Dispose()
        {
            Dispose(true);
            // This object will be cleaned up by the Dispose method.
            // Therefore, you should call GC.SupressFinalize to
            // take this object off the finalization queue
            // and prevent finalization code for this object
            // from executing a second time.
            GC.SuppressFinalize(this);
        }

        // Dispose(bool disposing) executes in two distinct scenarios.
        // If disposing equals true, the method has been called directly
        // or indirectly by a user's code. Managed and unmanaged resources
        // can be disposed.
        // If disposing equals false, the method has been called by the
        // runtime from inside the finalizer and you should not reference
        // other objects. Only unmanaged resources can be disposed.
        protected virtual void Dispose(bool disposing)
        {
            // Check to see if Dispose has already been called.
            if(!this.disposed)
            {
                // If disposing equals true, dispose all managed
                // and unmanaged resources.
                if(disposing)
                {
                    // Dispose managed resources.
                    component.Dispose();
                }

                // Call the appropriate methods to clean up
                // unmanaged resources here.
                // If disposing is false,
                // only the following code is executed.
                CloseHandle(handle);
                handle = IntPtr.Zero;

                // Note disposing has been done.
                disposed = true;

            }
        }

        // Use interop to call the method necessary
        // to clean up the unmanaged resource.
        [System.Runtime.InteropServices.DllImport("Kernel32")]
        private extern static Boolean CloseHandle(IntPtr handle);

        // Use C# destructor syntax for finalization code.
        // This destructor will run only if the Dispose method
        // does not get called.
        // It gives your base class the opportunity to finalize.
        // Do not provide destructors in types derived from this class.
        ~MyResource()
        {
            // Do not re-create Dispose clean-up code here.
            // Calling Dispose(false) is optimal in terms of
            // readability and maintainability.
            Dispose(false);
        }
    }
    public static void Main()
    {
        // Insert code here to create
        // and use the MyResource object.
    }
}









'프로그래밍 > C#' 카테고리의 다른 글

C# Programming Guide - Arrays  (0) 2017.05.09
Tuple Class  (0) 2017.05.08
.NET Framework Regular Expressions  (0) 2017.05.08
Data Parallelism (Task Parallel Library)  (0) 2017.05.06
Task  (0) 2017.04.22
:
Posted by 지훈2