static constructor vs instance constructor

C#은 두 가지 종류의 constructor, 즉 class constructor(static constructor), instance constructor(non-static constructor)를 지원한다.

static constructor
-static constructor는 static data member를 초기화하는데 사용
-static constructor는 접근 지정자를 쓸수 없음
-static constructor는 인자를 가질 수 없음
-static constructor는 non-static data member를 접근할 수 없음

// Test.cs
Test
{
//Declaration and initialization of static data member
private static int id = 5;
public static int Id
{
get
{
return id;
}
}

public static void print()
{
Console.WriteLine(“Test.id=” + id);
}
}

class Program
{
static void Main(string[] args)
{
Test.print(); // 정적 메소드를 사용하여 Test.id를 출력
}
}
Test.id=5

// Test1.cs
class Test1
{
private static int id;

// static constructor를 사용하여 Test.id값에 따라서 Test1.id를 지정
static Test()
{
if( Test.Id < 10 ) { id = 20; }
else { id = 100; }
}

public static void print()
{
Console.WriteLine(“Test.id=” + id);
}
}

class Program
{
static void Main(string[] args)
{
Test1.print(); // 정적 메소드를 사용하여 Test.id를 출력
}
}

Test.id=20 // 정적 생성자 내에서 Test.id=5였기때문에 Test.id=20

instance constructor
-instance constructor는 new 키워드를 사용하여 객체 생성에 사용
-instance constructor는 일반적으로 constructor라고 불림
-constructor initializer는 생성자들 코드를 간략하게 만들기 위해 사용

public class MySimpleClass
{
public MySimpleClass (int x)
{
Console.WriteLine (x);
}
}

// 위의 코드는 컴파일러에서 아래의 코드처럼 해석
public class MySimpleClass
{
public MySimpleClass (int x) : base()
{
Console.WriteLine (x);
}
}

public class MyClass {
private ArrayList col;
private string name;
public MyClass() : this(0,””) // 생성자 초기화목록을 사용하여 기본 생성자 지정 { }
public MyClass(int initialCount) : this (initialCount, “”) { }
public MyClass(int initialCount, string name)
{
col = (initialCount > 0) ? new ArrayList(initialCount) : new ArrayList();
this.name = name;
}
}

-default constructor가 지정되어 있지 않다면 컴파일러에서 자동 생성해줌

public class MySimpleClass
{
int someMemberVariable;
}

// 위의 코드를 컴파일러에서 아래와 같이 해석함
public class MySimpleClass
{
int someMemberVariable;public MySimpleClass() : base()
{
}
}

-constructor는 상속되지 않음

public class MyBaseClass
{
public MyBaseClass (int x)
{
}
}

public class MyDerivedClass : MyBaseClass
{
// This constructor itself is okay – it invokes an
// appropriate base class constructor
public MyDerivedClass () : base (5)
{
}

public static void Main()
{
new MyDerivedClass (10); // ERROR: MyDerivedClass는 인자를 받는 생성자가 없음
}
}

Private constructor vs Protected constructor

private constructor는 정적 메소드와 속성 (static method & property)만 있는 경우 사용함.
http://msdn.microsoft.com/en-us/library/vstudio/kcfb85a6.aspx

public class Counter
{
private Counter() { }
public static int currentCount;
public static int IncrementCount() { return ++currentCount; }
}
class TestCounter
{
static void Main()
{
// If you uncomment the following statement, it will generate
// an error because the constructor is inaccessible:
// Counter aCounter = new Counter(); // Error
Counter.currentCount = 100;
Counter.IncrementCount();
Console.WriteLine(“New count: {0}”, Counter.currentCount);
// Keep the console window open in debug mode.
Console.WriteLine(“Press any key to exit.”);
Console.ReadKey();
}

} // Output: New count: 101

protected constructor는 추상클래스 (abstract class)에서 사용을 권고함. 추상 클래스를 상속받는 파생클래스에서 파생 클래스 생성자가 부모 클래스 즉, 추상 클래스를 초기화 하기 위해 추상 클래스 생성자를 호출 할 수 있도록 지원함.
http://msdn.microsoft.com/en-us/library/bcd5672a%28v=vs.80%29.aspx
http://msdn.microsoft.com/ko-kr/library/ms229047(v=vs.100).aspx

public abstract class Shape
{
protected Shape(string name) { this.name = name; }
private string name;
public virtual void Print() { Console.Write(this.name); }
}
public class Triangle: Shape
{
public Triangle(string name): base(name) { this.bottom = 1; this.height = 1 }
private double bottom, height;
public override void Print()
{
base.Print();
Console.WriteLine(” 밑변: {0} 높이: {1}”, this.bottom, this.height);
}
}
public class Rectangle: Shape
{
public Rectangle(string name): base(name) { this.width = 2; this.height = 3 }
private double width, height;
public override void Print()
{
base.Print();
Console.WriteLine(” 가로: {0} 세로: {1}”, this.width, this.height);
}
}
class ShapeTest
{
static void Main()
{
// Shape s = new Shape(“도형”); // Error CS0144, Cannot create an instance of the abstract class
Shape s = new Triangle(“삼각형”);
s.Print(); // 삼각형 밑변: 1 높이: 1
s = new Rectangle(“직사각형”);
s.Print(); // 직사각형 가로: 2 세로: 3
}
}

 

 

Lab2

Lab2 프로젝트 디렉토리 안에 모든 파일과 코드분속 보고서 (2~3장)를 넣고 Lab2_학번_이름.zip 압축한 후 e-learning(http://lms.dankook.ac.kr/index.jsp)으로 제출 (10점)
Lab2 – Basics (method, for, foreach, if, switch, do/while, while, array 활용)
수업블로그에 2.Basic 안에 TemperatureConverter 클래스 참고하여, 본인이 원하는 Converter 클래스를 추가작성한다 (예시: degree <-> radian 변환, kilometer <-> mile 변환, kilogram <-> pound 변환, 등등).
http://www.unitconverters.net/

Object-Oriented Programming (OOP)

Class – defines the grouping of data and code, the “type” of an object
Instance – a specific allocation of a class
Message – sent to objects to make them act
Method – a “function” that an object knows how to perform
Instance Variables – a specific piece of data belonging to an object
Property – away to access instance variables and other attributes of an object
Encapsulation – keep implementation private and seperate from interface
Polymorphism – different objects, same interface
Inheritance – hierarchical organization. share code, customize or extend behaviors

Lab1

Lab1 프로젝트 디렉토리 안에 모든 파일과 보고서 (2~3장)를 넣고 Lab1_학번_이름.zip 압축한 후 e-learning(http://lms.dankook.ac.kr/index.jsp)으로 제출 (10점)

Lab1 – Basics (method, for, foreach, if, switch, do/while, while, array 활용) 코드 분석 보고서 & (수업블로그에 4.Basic 안에 ArithmeticOperator 클래스 참고하여) 본인이 원하는 method나 routine를 추가 작성한다.

4.Basic

보고서는 출력해서 수업시작 전에 제출한다.

Why need boxing and unboxing

Why do we need boxing and unboxing in C#?
http://stackoverflow.com/questions/2111857/why-do-we-need-boxing-and-unboxing-in-c

 

struct Point
{
public int x, y;
public Point(int x, int y)
{
this.x = x;
this.y = y;
}
public override string ToString()
{
return String.Format(“{0} {1}”, this.x, this.y);
}
}
class Point2
{
public int x, y;
public Point2(int x, int y)
{
this.x = x;
this.y = y;
}
public override string ToString()
{
return String.Format(“{0} {1}”, this.x, this.y);
}
}
class Program
{
static void Print(object o)
{
Console.WriteLine(o);
}
static void Main(string[] args)
{
int x = 4;
Print(x); // boxing (int=>object)
double y = 3.2;
Print(y); // boxing (double=>object)
char z = ‘n’;
Print(z); // boxing (char=>object)
double e = 2.718281828459045;
object o1 = e; // boxing (double=>object)
object o2 = e; // boxing (double=>object)
Console.WriteLine(o1 == o2); // False (o1과 o2는 서로 다른 메모리에 데이타 복사본 저장)
Point p3 = new Point(1, 1);
Print(p3); // boxing (struct=>object)
object o3 = p3; // boxing (struct=>object)
p3.x = 2;
//((Point)o3).x = 4; // CS0445 Cannot modify the result of an unboxing conversion 
Console.WriteLine(((Point)o3).x); // 1  unboxing(object=>struct) o3.x=1 (o3는 박싱된 복사본 p3에의해 데이터 안바뀜)
Point2 p4 = new Point2(1, 1);
Print(p4); // boxing 아님
object o4 = p4; // boxing 아님
p4.x = 2;
Print(p4); // upcasting(Point2 class=>object) 2 1
((Point2)o4).x = 4; // downcasting(object=>Point2 class) o4.x=2 (class는 reference type이므로 o4는 p4에의해 데이터가 바뀜)
Console.WriteLine(p4); // p4.ToString()호출 4 1
}
}

Boxing과 Unboxing을 최소화하라

Boxing은 값 형식 (value type)을 참조 형식 (reference type)으로 변경하는 것이다.
Boxing을 수행하면 힙 상에 새로운 reference type 객체가 생성되고 value type의 객체가 가지고 있던 값이 reference type 객체 내부로 복사된다.
새로 생성된 reference type 객체는 내부적으로 value type 객체의 복사본을 포함하고, value type에서 제공하였던 interface를 그대로 재구현한다.

Unboxing은 참조 형식 (reference type)을 값 형식 (value type)으로 변경하는 것이다.
만약 reference type 객체 내부에 포함된 value type 객체의 값을 얻고자 시도하면 복사본을 만들어서 돌려준다.

Console.WriteLine(“Numbers: {0}, {1}, {2}”, 10, 20, 30);
Console.WriteLine()은 System.Object의 배열을 인자로 받는데, 정수들은 모두 value type이기때문에 value type의 인자로 전달하기 위해서는 reference type으로 boxing이 수행된다.
Boxing과 Unboxing 동작은 필요시 자동적으로 일어나며, 이 과정에서 컴파일러는 어떠한 경고도 발생시키지 않는다. WriteLine(…)을 호출할 때에는, 아래와 같이 value type을 string type instance로 변경하는 것이 좋다.
Console.WriteLine(“Numbers: {0}, {1}, {2}”, 10.ToString(), 20.ToString(), 30.ToString());
이 코드는 string type을 사용하기 때문에 value type들은 더이상 System.Object 로 변경되지 않는다.