dll 사용의 문제점

  1. 배포의 문제. 설치가 끝난 프로그램은 절대경로로 dll을 찾으려고 한다. 경로가 바뀐것이 제때 갱신 되지 않으면 프로그램은 정상 동작할수 없다
  2. DLL지옥이란 문제가 발생한다
  3. DLL도 결국에 파일이기때문에 보안에 취약하다

 

어셈블리는 어셈블리메타데이타, 타입메타데이타, MSIL코드, 리소스 등으로 구성되어 있다.

어셈블리 메타데이터를 저장하는 장소가 manifestr이다.

어셈블리 이름 - 어셈블리의 이름을 문자열 형태로 저장

버전 번호 - 버전

컬쳐 - 지원하는 언어

강력한 이름 - 공유 어셈블리의 작성자와 공개키를 나타내는 정보

파일목록 - 다중 파일 어셈블리에 포함되는 파일의 이름과 해시이다. 이 파일들은 매니페스트가 잇는 디렉토리와 같은 위치에 있어야 한다

참조타입 - 어셈블리에서 외부로 노출하는 클래스에 대한 정보

참조하는 타입 - 어셈블리가 참조하는 다른 어셈블리의 목록이다.

이밖에 커스텀 애트리뷰트(상표나 저작권, 개발사, 개발자 등)을 추가할수 있다.

어셈블리는 스스로 설명 가능한 모듈이라고 하는데 이는 자신의 모든 정보를 스스로 보유한다는 뜻이다.

MSIL 은 어셈블리의 소스코드를 중간 코드 로 변환한 것이다.

 

다중파일 어셈블리 - 일반적으로 하나의 프로젝트나 소스로 하나의 어셈블리를 만든다. 몇몇 특수한 경우에 여러개의 파일로 구성된 어셈블리를 만들수도 있다. 그러면 각 파일은 모듈이 되고 그 모듈들이 모여서 하나의 어셈블리 역할을 하게 된다. 이것은 일반적인 경우가 아니다. 이런 기능을 지원하는 이유는 같은 모듈을 다른 언어로 각각의 개발자가 개발할때라던지 다운로드의 효율성을 높이기 위해서이다.

 

 

공유어셈블리

전용어셈블리 - 특정 클라이언트 혼사서만 사용하는 어셈블리이다. 봍오 클라이언트 실행파일이 있는 디렉토리 위치하여 클라이언트와 함께 배포된다. 클라이언트가 실행될때 메모리로 같이 로드되며 별도의 버전 체크를 하지 않는다. 클라이언트와 같은 디렉토리에 있으므로 관리하기 쉽다. 다른 프로그램에도 영향을 주지 않는다

공유어셈블리 - 블특정한 다수의 클라이언트들이 사용하는 어셈블리이다. 누구나 어셈블리를 로드해서 사용할수 있어야 하므로 GAC(Global Assembly Cache)라는 약속된 디렉토리에 위치한다

(WINDOWS\Assmbly\) 한 디렉토리에 굉장히 많은 전용 어셈블리들이 같이 저장되니까 상호구분을 위해서 강력한 이름을 붙여 서로를 엄격하게 구분한다. 공유 어셈블리를 만들려면 강력한 이름을 부여해야 한다. 강력한 이름은 어셈블리를 유일하게 구분하는 일종의 식별자로서 COM의 GUID에 해당하는 값이다. 강력한 이름에는 문자열로 된 어셈블리의 이름과 버전 정보, 공개키와 컾쳐 정보가 포함된다. 공개키/개인키라는

암호화기법을 사용한다. 공개키는 어셈블리의 유일성을 보증하는 역할을 하며 또한 어셈블리를 함부로 수정하지 못하도록 방지하는 보안의 역할까지 담당한다. 공개키, 개인키 쌍은 sn.exe로 만들고 snk라는 확장자를 가지는 파일을 생성한다. 공유어셈블리는 탐색기에서 복사할 수도 잇지만 gacutil을 이용하는 것이 훨씬 좋다.

 

병렬설치

공유 어셈블리는 이름이 같은 여러개의 버전을 하나의 시스템에 동시에 설치할수도 있다. 같은 어셈블리가 설치되면 그 이름의 폴더가 생기가 그 하위에 버전이름 폴더가 생긴 다음에 그 폴더에 dll이 복사가 된다

다른 버전의 어셈블리가 설치된다면 이름폴더 아래 다른 버전이름의 폴더가 생기고 그 하위에 dll이 복사가된다. 즉 버전별로 다른 폴더가 각각 생기는 것이다.

 

프로빙

클라이언트가 어셈블리의 위치를 찾아내는 방법을 probing / resolve라 한다. 클라이언트의 매니페스트에는 어떤 어셈블리가 필요하다는 정보가 기록되어 있으므로 이 정보를 참조하여 어셈블리의 위치를 찾아 로로한다.

구성파일 - 실행파일 폴더 하위에 있는 경우 그 경로에 대한 정보를 가지고 있는 .config파일. 이름은 실행파일이름.exe.config라 짓는다

코드베이스 -  공유어셈블리를 GAC가 아닌 네트워크 경로나 웹서버에 둘수 있다.

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <runtime>
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
      <dependentAssembly>
        <assemblyIdentity name="MyShareDLL" publicKeyToken="aslkdjasd" culture="neutral">         
        </assemblyIdentity>
        <codebase version"2.0.0.0" href="http://www.winapi.co.kr/data/MyShareDLL.dll"></codebase>
      </dependentAssembly>
     
    </assemblyBinding>
  </runtime>
</configuration>
이런 식의 원격 프로빙 방법을 제공하는 이유는 어셈블리의 중앙통제를 위해서이다. 단, 네트워크가 끊어지면 곤란한 상황이 발생한다는 단점이 있다.

ex.

이 글은 스프링노트에서 작성되었습니다.

by 무위자연 2008. 8. 27. 17:02

닷넷프로그래밍정복 김상형저 가메출판사

Languate INtegrated Query(.Net 3.5이상에서 지원)

쿼리란 데이터 소스에서 특정고전에 맞는 데이터를 검색하는 지시사항이다.

LINQ는 언어에 독립적인 쿼리문이다. 여기서 언어라는 용어는 이중의 의미를 가진다. 쿼리 대상인 데이터소스를 칭하기도 하고 쿼리 실행언어를 칭하기도 하는데 양쪽 다 독립적이다.

LINQ는 쿼리문에 객체지향 개념을 도입하였고 인텔리센스나 디버거의 도움도 쉽게 받을수 있다. 데이터변경은 불가능하고 정렬이나 그룹핑정도만 가능하다. 향후 발전 가능성은 높으나

아직은 베타수준이라 지원하는 언어도 C#3.0 / VB9.0뿐이고 결과도 COM처럼 될지 안될지는 두고 볼일이다.

ex1. SQL 문과 유사한 점이 많다

int[] ar = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
            IEnumerable<int> Query = from n in ar where ( n % 3 == 0 ) select n;
            foreach(int k in Query)
                Console.WriteLine(k);

ex2

 var Files = from f in Directory.GetFiles("c:\\") select f;
            foreach (var f in Files)
                Console.WriteLine("이름 " + f);

데이터 소스의 최소요건인 열거가능만 갖추어지면 DB / XML / FILE정보 등 활용을 다양하게 적용할수 있다

 

쿼리 표현식

from - where        -  select

           orderby        group

           let

의 형식을 가지고 있고 from으로 시작해서 select 식으로 끝난다.

형식은 순회변수 in 데이터 소스

순회변수의 타입은 비제네릭일때는 명시해야 하고 그렇지 않으면 굳이 명시하지 않아도 좋다

 

표준쿼리 처리자

쿼리표현식은 불행히도(!) 언어의 기능일뿐 닷넷 자체의 기능이 아니다. 그래서 모든 쿼리는 CLR이 이해할수 있는 메소드로 번역되어야만 실행할수 있다. 가급적 가독성을 높이기 위해서 쿼리문을 쓰는 것이 좋지만 아직까지 모든 쿼리문을 표현하지는 못한다. 그럴떄는 부득이하게 메소드를 바로 호출하게 된다.

  • Count  개수를 구한다
  • Sum 합계를 구한다
  • Average 평균을 구한다
  • Max 최대값을 구한다
  • Min 최소값을 구한다
  • OrderBy 요소등을 정렬한다
  • Select 결과셋의 프로젝션을 생성한다
  • Distnct 중복을 제거한다
  • Except 차집합을 구한다
  • Intersect 교집합을 구한다
  • Union 합집합을 구한다
  • All 모든 요소가 조건을 만족하는지 조사한다
  • Any 하나의 요소라도 조건을 만족하는지 조사한다
  • Contains 지정한 요소가 포함되어 있는지 조사한다
  • Take 지정한 위치에서 컬렉션을 분할한다
  • First 컬렉션의 첫번째 요소를 구한다
  • Last 컬렉션의 마지막 요소를 구한다
  • ElementAt 지정한 첨자의요소를 구한다

 

쿼리의 실행

쿼리를 생성하는 것과 실행하는 것은 별개이다. 쿼리를 생성하는 것은 단지 데이터를 읽을 준비만 하는 것이며 쿼리에 의해 생성된 결과셋을 순회하면서 읽어야 비로소 원하는 데이터를 얻을수 있다. 이것을 지연된 실행

(Deferred Execution)라고 한다.

ex.

int[] ar = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
            IEnumerable<int> Query = from n in ar select n; // 쿼리 생성
            foreach (int k in Query) //데이타 셋 순회
                Console.WriteLine(k);

            Console.WriteLine();
            ar[2] = 9999;//데이타 셋에 반영 안됨
            foreach (int k in Query)//데이타 셋 순회
                Console.WriteLine(k);

쿼리를 실행할때마다 다른 결과가 리턴될수 있는데 이를 현재성이라고 한다. 순회시점의 정확한 값을 실시간으로 저사함으로써 현재성이 높다. 지연된 실행은 성능향상에 유리하다. 하지만 예외도 있다. 단일값을 반환하는 Count 류 함수는 굳이 지연시킬 필요가 없으니까 바로 반환한다.

 

 

고급쿼리

2.1 프로젝션 - 결과셋의 출력형태를 데이터 소스와는 다르게 변형하는 것

ex.

 People[] arPeople = { new People("한가인",18, true),
                                    new People("한예슬", 19, false),
                                    new People("남상미", 20, true),
                                    new People("강성연", 21,false) };


            IEnumerable<ResultNameAge> Query = from p in arPeople select new ResultNameAge(p.Name, p.Age);

            foreach (ResultNameAge k in Query)
                Console.WriteLine("이름 {0} 나이 {1}", k.Name, k.Age);

결과셋은 쿼리문에서 딱 한번 쓰고 말 것이니까 굳이 클래스로 선언하지 않고 원하는 멤버들로 구성된 객체를 생성할수 있다.

var Query = from p in arPeople select new { Name = p.Name, Age = p.Age };

이것을 익명타입으로 바꾼다면,

var Query = from p in arPeople select new { p.Name, p.Age };

익명타입이 다른 타입의 부분 집합일 경우 멤버의 이름을 생략하면 원본 타입의 이름을 그대로 따른다는 규칙이 있다.

 

그리고 프로젝션 기능으로  XML로 결과물을 만들어낼수 있다.

ex.

 var Query = new XElement("사람들", from p in arPeople
                                            select new XElement("사람",
                                                new XElement("이름", p.Name), new XElement("나이", p.Age),
                                                new XElement("남자", p.Male)));
Console.WriteLine(Query);

 

2.2 필터링 및 정렬

where 절 - 이 조건에 맞는 항목만 출력한다

orderby 절 - 결과셋의 출력순서를 지정한다. 디폴트는 오름차순이고 내림차순을 원할떄는 끝에 descending 붙여야 한다.

let 절 - 결과셋을 가공하여 임시변수에 저장하는 역할을 한다. 쿼리문 내에서 임시로 사용할 변수가 필요할때 let문으로 변수를 선언하고 이후 출력이나 조건, 점검 등에 이 변수를 활용할수 있다.

 

2.3 그룹핑

group by 절 - 특정 키를 기준으로 하여 요소들을 그룹별로 구분하여 출력하는 것이다. 그룹핑을 위해서는 내부적으로 키를 기준으로 정렬하고 같은 키를 가진 요소들을 소그룹으로 엮는 번잡한 처리를 해야 한다.

ex.

class Staff
{
    public Staff(string aName, string aDepart, int aSalary)
    {
        Name = aName;
        Depart = aDepart;
        Salay = aSalary;
    }
    public string Name;
    public string Depart;
    public int Salay;

}

 

 Staff[] arStaff = { new Staff("김유진", "초등부", 180),
                                  new Staff("김유경", "대학부", 195),
                                  new Staff("김상아", "초등부", 175),
                                  new Staff("김소연", "초등부", 170),
                                  new Staff("손화진", "중등부", 180),
                                  new Staff("곽민지", "중등부", 200),
                                  new Staff("허소림", "대학부", 210),
                                  new Staff("노찬영", "대학부", 187),
                                  new Staff("임유미", "고등부", 130),
                                
                              };

            IEnumerable<IGrouping<string, Staff>> Query = from p in arStaff group p by p.Depart;

            foreach(IGrouping<string, Staff>g in Query)
            {
                Console.WriteLine("\r\n" + g.Key);
                foreach(Staff k in g)
                    Console.WriteLine("이름 {0} 월급 {1}", k.Name, k.Salay);

            }

타입을 쓰면 복잡할수 있으니 암묵적 타입을 쓰면 var 훨씬 간단해진다.

ex

 var Query = from p in arStaff group p by p.Depart;

            foreach (var g in Query)
            {
                Console.WriteLine("\r\n" + g.Key);
                foreach (Staff k in g)
                    Console.WriteLine("이름 {0} 월급 {1}", k.Name, k.Salay);

            }

 

into 절 - let 절과 비슷한데 그룹핑 또는 조인한 쿼리에 임시적인 식별자를 부여하는 역할을 한다.

ex var Query = from p in arStaff group  p by p.Depart into gp orderby gp.Key. Select gp;

 

서브쿼리와 조인

서브쿼리는 쿼리문안에ㅔ 또 다른 쿼기가 있는 것이다. 연ㅅ곡되는 질문을 하나로 합칠수 있으며 SQL의 서브쿼리와 개념상 동일하다.

ex var Query = from p in arStaff where p.Salary == (from p2 in arStaff select p2.Salary).Max() select p.Name;

이 글은 스프링노트에서 작성되었습니다.

by 무위자연 2008. 8. 27. 15:03

닷넷프로그래밍정복 김상형저 가메출판사

 

2.1 자동구현 프로퍼티

 get, set만 선언하면 프로퍼티로 사용할수 있는 기능이 지원된다. 단 자동구현 프로퍼티는 반드시 get/set 모두 있어야 한다.

ex)

class Human
{
    public string Name { get; set; }
    public int Age { get; set; }
}
namespace Example2
{
    class Program
    {
        static void Main(string[] args)
        {
            Human Lee = new Human();
            Lee.Name = "나영";
            Lee.Age = 18;

            Console.WriteLine("이름은 {0} 나이는 {1}", Lee.Name, Lee.Age);
        }
    }

 

2.2 초기자

객체초기자 - 클래스의 객체를 선언과 동시에 초기화하려면 생성자가 필요하고 생성자에 인수를 전달해야 한다. 객체초기자를 사용하면 생성자가 없어도 외부에서 필드나 프로퍼티에 원하는 값을 대입하여 객체를 초기화할수 있다.

형식 : new 클래스(생성자 인수) { 멤버 = 값, 멤버 = 값};

생성자 인수는 생략할수 있고 {}안에서는 명령문이 아니니까 ";"이 없어야 하나 {}다음엔 반드시 ";"이 와야 한다. 초기자의 대상은 public 이어야 한다.

 

중첩객체초기화 - 다른클래스에 중첩된 객체도 초기자 문법으로 초기화할수 있다.

ex.

class Human

{

public string Name;

public  int Age;

}

class Couple

{

public Human Husband;

public Human Wife;

}

위와 같이 클래스를 선언했을 경우 다음과 같이 초기화를 진행하게 된다.

static void Main()

{

Couple Inko = new Couple();

            Inko.Husband = new Human();
            Inko.Husband.Name = "차인표";
            Inko.Husband.Age = 40;
            Inko.WIfe = new Human();
            Inko.WIfe.Name = "신애라";
            Inko.WIfe.Age = 38;

            Console.WriteLine("남편 : {0}세 {1}, 아내 : {2}세 {3}", Inko.Husband.Name, Inko.Husband.Age,

                Inko.WIfe.Name, Inko.WIfe.Age);

}

 

초기자를 쓴다고 하면

 Couple Inko = new Couple
            {
                Husband = new Human { Name = "차인표", Age = 40 },
                WIfe = new Human { Name = "신애라", Age = 38 }
            };

이런식이 가능하다. 그리고 Couple class를 다음과 같이 선언했다면

class Couple

{

public Human Husband = new Human();

public Humna Wife = new Human();

}

 

Couple Inko = new Couple
            {
                Husband = { Name = "차림표", Age = 40 },
                WIfe = { Name = "신애라", Age = 38 }
            };

처럼 각 Human 타입을 생성하지 않아도 되는 편리함이 생긴다.

 

컬렉션초기자- 컬렉션 초기자를 사용하기 위해서는 ICollection<T> 를 상속받은 객체여야 하고 방법은 배열 초기화와 비슷하다

ex. List<string> ar = new List<string> {"노찬영", " 민혜경", "이단비"};

 

초기자의 혼용 - 객체 초기자와 컬렉션 초기자를 같이 사용할수 있다.

ex

class Bbar

{

public string Name;

public List<string> Idol = new List <string>;

}

 

stastic void Main()

{

var girls = new List<Bbar>

{

new Bbar { Name = "한가인", Idol = {"김동현", "장동건", "이정재" }},

new Bbar { Name = "한예슬", Idol = {"김동현", "비", "박시후" }},

new Bbar { Name = "한은정", Idol = {"김동현", "장근석", "지현우" }}

}

}

 

2.3 익명타입 - 딴 한번만 사용할 타입이라면 굳이 타입을 선언한 후 객체를 생성할 필요가 없으니 타입정의와 객체 생성을 한번에 처리하기 위한 타입.

형식 : var 객체 = new { p1 = v1, p2 = v2};

ex.

var Nam = new { Name = "남상미", Age = 26 };
Console.WriteLine("이름 {0 } 나이는 {1}", Nam.Name, Nam.Age);

익명타입은 주로 메소드 내에서 지역적으로 사용된다. 이름이 없으므로 메서드 바깥으로 전달하거나 컬렉션에 저장한다는가 할수는 없다. 그리고 LINQ에서 유용하다.

 

람다표현식

3.1 확장메소드 - 기존의 클래스는 그대로 유지한태로 메서드를 추가할수 있는 방법을 제공한다. 확장메서드 자체는 별로도 정의되지만 마치 클래스에 원래부터 속해 있는 메서드처럼 호출할수 있다.

확장메서드를 담는 정적클래스는 어디까지나 확장 메서드를 담는 통에 불과하므로 이름은 아무렇게나 붙여도 상관없다. 정적클래스는 외부의 네임스페이스에 선언되어 있어도 무관하다. using문은 네임스페이스 내의 정적 클래스를 모두 검색하여 정의되어 있는 확장 메서드를 자동으로 import한다. 또한 컴파일러는 확장 메서드를 호출할때  import된 모든 확장 메서드를 검색하여 위치를 자동으로 찾아낸다. 사용자가 할일은 확장메서드가 정의된 네임스페이스를 using 선언으로 import하는 것뿐이며 나머지 모든 처리는 컴파일러가 알아서 한다. 확장메서드는 실제로 클래스에 소속된 것이 아니다. 하지만 호출문법이 동일해서 외북에서 보기에는 마치

클래스에 소속된 인스턴스 메소드처럼 보인다. 그래서 기존의 완성된 클래스를 최종 사용자에게 혼란을 주지 않고 확장할수 있는 좋은 방법이다.

ex

public class Integer
{
    public int a;
    public Integer(int aa) { a = aa; }
    public int Add(int b) { return a + b; }
    public int Mul(int b) { return a * b; }
}

public static class IntegerEx
{
    public static int Sub(this Integer l, int b)
    {
        return l.a - b;
    }
}

처름 Integer class에서는 Sub가 구현되어 있지 않았다.

하지만

Integer Num = new Integer(3);
            Console.WriteLine("덧셈 : " + Num.Add(2));
            Console.WriteLine("뺄셈 : " + Num.Sub(2));
            Console.WriteLine("곱셈 : " + Num.Mul(2));

마치 원래 있던 것처럼 사용할수 있다.

 

3.2 람다표현식 > 코드를 별도의 메소드 정의 없이 인라인으로 바로 작성할 수 있는 방법이다. 익명메소드와 유사하지만 세가지가 다르다

  1. 인수 타입을 생략할 수 있다. 생략된 타입은 델리게이트의 타입을 따른다
  2. 본체에 명령문뿐 아니라 표현식도 쓸수 있어 좀 더 짧다
  3. 표현식 트리로도 변환할수 있다

형식 (인수) => 표현식 또는 명령문

ex. 익명 메소드로 표현하면

delegate int dele(int a);

dele d = delegate(int a) { return a + 1 };

람다표현식으로 하면

dele d= a => a + 1;

 

이 글은 스프링노트에서 작성되었습니다.

by 무위자연 2008. 8. 27. 11:39

닷넷프로그래밍정복 김상형저 가메출판사

1.제네릭

타입인수

제네릭(Generic)은 타입 인수를 사용하여 일반화된 클래스나 메서드를 정의하는 기법이다. 제네릭은 템플릿과 유사하다. 코드의 재사용성을 높이고 타입 안전성을 극대화하는 장점이 있는 반면, 코드의 크기가 커지고 가독성이 떨어지는 단점이 있다. 가독성이 나쁘다는 것은 유지, 보수 비용이 커지고 개발기간을 늘리니까 심한 중첩은 삼가고 적당한 수준에서 사용해야 한다. 공통된 인자를 타입인수(Type Parameter)라 하고 T-임의의-실제 타입을 위한 자리 표시이며 실제 타입은 객체를 생성할때 지정된다. 타입인수는 필요한 모든 곳에 사용가능하다. 타입인수 이름은 가급적 설명이 있는 이름이 좋으나 간단한 것이라면 통상적으로 T, U, V 식으로 간단하게 짓는다.

ex.

class Wrapper<T>

{

T value;

public Wrapper() { Value = default(T);}

public Wrapper(T aVAlue) { Value = aValue; }

public T Data

{

get { return Value;}

set { Value = value;}

}

public void OutValue()

{

Console.WRiteLine(Value);

}

}

class CSTest

{

static void Main()

{

Wrapper<int> gi = new Wrapper<int>(1234);

gi.OutValue();

Wrapper<string> gs = new Wrapper<string>("문자열");

gs.OutValue();

}

}

제약조건 - 제네릭 선언문에 where와 함께 지정할수 있다.

ex.

class Wrapper<T> where T : struct -> T는 값 타입이어야 하고 참조 타입은 쓸수 없다. 단, Nullable타입은 값타입이지만 예외적으로 이 경우에 허용되지 않는다.

{

 //...

}

이 중 가장 실용적인 것은 where T : base인데 Base 및 그 파생클래스를 마음껏 쓸수 있는 장점이 있다. 만약 제약조건이 없다면 default가 object class인데 이것만으론 별 쓸모가 없다.

제네릭컬렉션

가변적인 자료의 집합을 관리하는 컬렉션은 모든 응용 프로그램에 필수적인 자료 구조이다.일반 컬렉션은 요소 타입은 object라 임의의 타입을 저장할수 있다. 어떤 객체든지 컬렉션에 넣을수 있으며 이를 막을수 있는 문법적인 방법이 전혀 없다.

ex.

static void Main()

{

ArrayList ar = new ArrayList(10);

ar.Add(1);

ar.Add(2.34);

ar.Add("string");

}

모든 타입이 object 파생클래스이기에 문법상 오류는 없다. 하지만 이것을 다루기 위해서는

  1. 번거롭게도 어떤 타입의 객체가 저장되는지 리스트에 저장하거나 접근시 어떤 객체 타입인지 확인해줘야 한다.  그렇게 안 하면 당장에 애러가 난다
  2. 혹은 캐스팅을 잘못햇을 경우에 위험하다. 다운위험성도 있다. C#은 이런 경우에 대비해서 is, as 연산자를 제공하지만 실행중에만 쓸수 있고 완전하지 않다.
  3. 값 타입을 컬렉션에 저장할때는 object타입으로 변환하는 박싱이 필요하고 꺼낼때는 언박싱이 필요하다. 이 동작자체는 컴파일러가 해주지만 성능저하를 피할수는 없다.

그래서 제네릭 컬렉션 클래스로 해결하려하는 것이다. 모든 제네릭 컬렉션 클래스는 System.Collections.Generic의 파생클래스이다. 제네릭의 타입체크는 엄격해서 엉뚱한 타입을 넣게 되면 바로 애러처리한다.

ex.

List <string > ar = new List<string > (10);

ar.Add("한가인");

ar.Add("차예련");

ar.Add("남상미");

ar.Add(1234); > string이 아니라서 바로 애러!!

ar.Add(5.678); > string이 아니라서 바로 애러!!

 

2.예외처리

예외(exception)이란 프로그램의 정상적인 흐름을 벗어나게 만드는 잘못된 조건이나 상태를 뜻한다. 일반적으로 조건문을 이용해서 예외처리를 할수도 있지만 원래 코드와 섞여서 좋지 않다.

그래서 특별힌 예외처리 구문을 사용하는 것이 좋다

  • try - 예외가 발생할만한 블록을 지정하며 이 블록 안에 코드를 작성한다. 이블록안에서 예외가 발생하면 catch로 점프하고 발생하지 않으면  catch를 무시하고 실행한다
  • catch - try에서 발생한 예외를 처리하는 블록이다. 발생한 예외객체를 인수로 전달받고 예외 종류별로 여러개의 catch블록을 사용할수 있다.
  • finally - 예외 발생 여부와 상관없이 반드시 처리해야하는 블록이다.

예외처리 구문은 컴파일러가 이전 단계를 찾아 점프하도록 코드를 생성하므로 단계가 아무리 깊어도 상관없다. 또한 중간 단계의 메소드에서 생성한 지역변수들도 모두 자동으로 해제되는데 이 기능을 스택풀기라고 한다.(stack unwinding) 최초 호출원에서 예외를 받아 처리했을때는 메소드를 호출하기 전의 상태로 스택이 그대로 복구되어 다음 명령을 정상적으로 실행할수 있다.

예외객체 - 예외에 대한 정보를 가지는 객체.System.Exception 파생클래스.

예외는 보통 라이브러리의 메소드 실행중에 발생하지만 우리가 직접 예외 객체를 생성하여 던질수도 있다. 예외를 던질때는 throw문을 사용하는데 이때 던져진 예외는 이어지는 catch문 또는 가장 가까운(!) catch문에서 받아 처리할 것이다.

ex.

static void AddKim(string Kim)

{

if(kim[0] != '김')

{

throw new FormatException("김가만 등록할수 있다");

}

Console.WriteLine(Kim + "등록완료");

}

사용자 예외를 정의할때는 ApplicationException을 상속받아야 한다. Exception class와 동일하지만 시스템 예외와 프로그램 예외를 구별하기 위해서 상속받는 것이다.

다중예외처리. - 하나의 코드 블록에서 여러가지 예외가 발생할수 있다. 이럴 때는 try 아래쪽에 발생 가능한 모든 예외에 대해 catch문을 나열하고 발생한 예외에 따라 각각 다르게 처리한다. 단, 가장 하위 예외 클래스가 가장 먼저 와야 한다.

 

3.기타타입

포인터 - C#에서는 포인터를 기본적으로 지원하지 않지만 참조타입으로 포인터를 교모하게 흉내낸다. 참조타입은  Framework에 의해 지원되며 GC가 철저히 관리해서 안전하다.

포인터는 다음 상황에서 필요하다

  1. 다른 언어와 함께 동작할때 - 특히 WInApi나 COM호출시
  2. 디버깅목적으로 메모리내부를 접근할때
  3. 학습목적으로 컴파일러나 프레임워크의 동작을 분석할때
  4. 극단적으로 성능을 높일때는 참조타입보다 포인터를 직접 쓰는 것이 유리하다. 실상 C#자체가 느려서 포인터를 써봐야 성능상 이점이 거의 없다

포인터를 쓰려면 빌드 옵션에서 "안전하지 않은 코드 허용"을 체크해야 하고 포인터 사용에 대한 책임은 전적으로 개발자가 진다. GC 손밖의 문제이다. 문법은 C와 거의 똑같다.

 

널가능타입  - 널은 값이라기 보다는 특정한 상태를 의미한다.

 

Attribute(속성)

컴파일러에게 코드에 대한 여분의 추가정보를 제공하는 선언형식. 적용대상 앞에 []와 속성명을 적고 속성명 다음의 ()안에 인수들을 지정한다.

공통애트리뷰트

Conditional:  namepsace System.Diagnostics

메소드의 컴파일 여부를 조건부로 결정한다. 정의부에만 conditional 애트리뷰트를 작성하면 호출부는 따로 처리하지 않아도 된다. 이 애트리뷰트는 특정 메소드에만 가능하고 클래스나 필드에는 적용할수 없다. 조건이란

  1. 인터페이스의 메소드 선언문에 쓸수 없고 인터페이스 구현메소드에서도 쓸수 없다.
  2. 가상 메소드에서는 쓸수 있지만 재정의 메소드에는 쓸수 없다.
  3. 조건에 따라 호출될수도 있고 아닐수도 있으므로 이 메소드가 없더라도 다른 부분이 영향을 받아서는 안된다. 그래서 중요한 메소드는 대상이 될수 없다. 그래서 리턴타입도 void만 가능하다. 조건부로 컴파일되는 메소드에 의존하는 다른 코드가 있다면 모두 조건부 처리해주어야 한다!

ex. #define TRIAL

 

 [Conditional("TRIAL")]
        static void TrialMessage()
        {

            Console.WriteLine("Trial Messages");
        }


        static void Main(string[] args)
        {
            TrialMessage();
            Console.WriteLine("Other Message");
        }

TRIAL이 define되어 있으면 TrialMessage가 호출되고 그렇지 않으면 호출되지 않는다. 만일 [Conditional("TRIAL"), Conditional("FREE")] 라고 애트리뷰트를 붙인다면 TRIAL이나 FREE가 정의되어 있다면 이란 조건이 된다. 두 조건은 AND로 만들려면 두개의 메소드를 정의한 다음에 한 쪽에서 다른 쪽을 호출하게 만들어야 한다.

ex. [Conditional("TRIAL")]

static void TrialMessage()

{

TrialMessage2();

}

[Conditioanl("FREE")]

static void TrilMessaeg2() {...}

 

Obsolete - 곧 폐기될 구식 코드임을 표시. 이 애트리뷰트가 붙은 요소를 사용하면 경고나 애러를 발생시켜 사용자의 사용을 막을 것을 알린다.

형식 [Obsolete("메세지", error)]

        대상

첫번째 인수는 경고나 오류메세지 문자열이다. 오류의 이유와 배경 등을 설명한다. 두번째 인수는 오류발생여부인데 이 인수가 true이면 애러 처리되어 컴파일이 거부된다. false이거나 생략하면 경고로 처리되는데 경고는 단순한 알림 서비스 일뿐 당분간 계속 쓸수 있다.

 ex.

[Obsolete("앞으로는 이 메소드를 쓰지 마시오", true)]

static public void OutDateMethod() {}

 

DllImport - 외부 DLL 함수를 선언할때 사용한다. COM 라이브러리 함수나 Win32API 함수를 사용하고 싶을때 이 애트리뷰트로 어떤 DLL에 있는 함수인지 밝힌다.

ex

using System.Runtime.InteropServices;

namespace FirstEx1
{
    class Program
    {
        [DllImport("User32.dll")]
        public static extern int MessageBox(int hPrarent, string Message, string CAption, int Type);

        [DllImport("Kernel32.dll")]
        public static extern uint WinExec(string Path, uint nCmdShow);
 

        static void Main(string[] args)
        {
            MessageBox(0, "메모장을 실행합니다", "알림", 0);
            WinExec("notepad.exe", 1);
        }
    }
}

둘 다 닷넷 외부의 DLL 정의된 함수이니까 extern을, 클래스 멤버가 아니니까 static이어야 한다. C 스타일의 메소드는 C#식으로 적당히 인수타입을 조정해야 한다. 문자열포인터는 string타입으로, unsigned는 unint로 바꾼다. 매크로 상수는 C에 정의된 것이니까 레퍼런스를 통해 알아낸 정수상수를 써야 한다.

 

커스텀애트리뷰트 - 컴파일 방식이나 생성되는 기계어 코드에는 전혀 영향을 주지 않으며 실행파일에 메타데이터로 포함될뿐이다. 코드에 설명을 다는 일종의 주석이라 할수 있고 일정화되어 있고 자동화된 처리가 가능하다는 점에서 일반 주석과 다르다.

ex.

[AttributeUsage(AttributeTargets.Method | AttributeTargets.Field, AllowMultiple = true, Inherited= false)]
class ProgrammerAttribute : Attribute
{
    private string Name;
    private string Time;
    public ProgrammerAttribute(string aName)
    {
        Name = aName;
        Time = "기록없음";
    }

    public string When
    {
        get { return Time; }
        set { Time = value; }
    }


}

namespace FirstEx1
{
    class Program
    {
        [Programmer("Kim")]
        static public int Field1 = 0;

        [Programmer("Kim", When = "2007년 6월 29일")]
        static public void Method1() {}

        [Programmer("Lee")]
        static public void Method2() { }

        [Programmer("Park"), Programmer("Choi")]
        static public void Method3() { }

        static void Main(string[] args)
        {
        }
    }
}

 이중에서 Method1의 metadata를 본다면

method public hidebysig static void  Method1() cil managed
{
  .custom instance void ProgrammerAttribute::.ctor(string) = ( 01 00 03 4B 69 6D 01 00 54 0E 04 57 68 65 6E 12   // ...Kim..T..When.
                                                               32 30 30 37 EB 85 84 20 36 EC 9B 94 20 32 39 EC   // 2007... 6... 29.
                                                               9D BC )
  // Code size       2 (0x2)
  .maxstack  8
  IL_0000:  nop
  IL_0001:  ret
} // end of method Program::Method1

Method3는

.method public hidebysig static void  Method3() cil managed
{
  .custom instance void ProgrammerAttribute::.ctor(string) = ( 01 00 04 50 61 72 6B 00 00 )                      // ...Park..
  .custom instance void ProgrammerAttribute::.ctor(string) = ( 01 00 04 43 68 6F 69 00 00 )                      // ...Choi..
  // Code size       2 (0x2)
  .maxstack  8
  IL_0000:  nop
  IL_0001:  ret
} // end of method Program::Method3

이런 식의 주석이 생기게 되는 것이다.

 

전처리문 - C++의 전처리기와 유사하고 C++형식을 빌려서 만든 문법이다.기계어 코드로 바뀌는 것은 아니지만 컴파일과 소스를 관리하는 방식에 영향을 미친다. C#에서 실제로 전처리 과정이 존재하지 않으며 컴파일러가 처리한다. 관습상 전처리 명령이라 부를뿐이다. 동작이나 용도는 같다. 단, 헤더파일을 include하는 #include는 없는데 C#은 선언 순서를 중요시 여기기 않는 언어이며 헤더파일이 없기때문이다.

ex #define, #undef 

존재만 정의하고 취소할뿐이고 using보다 앞에 와야 한다.

조건부 지시자에는 #if #else #elif #endif 등이 있고

애러처리시엔 #warring, #error를 사용하고

코드 블록을 임의로 묶을때는

#region 과 #endregion을 pair로 쓴다.


 

 

 

이 글은 스프링노트에서 작성되었습니다.

by 무위자연 2008. 8. 26. 14:29

닷넷프로그래밍정복 김상형저 가메출판사

1.Root Class - Object class

C#은 모든 클래스와 객체는 BCL(base class library)에 정의한 기본 클래스에 정의된 object 클래스(루트클래스)에서 모두 파생된다.

System.Object.Obj ; // 가장 정확한 표현

Object.Obj;            //네임스페이스 생략

object.Obj;            //언어의 별칭 사용

System.object.Obj;//틀린 표현!!!

Object 기본 메소드

  • ToString
  • GetType
  • MemberwiseClone
  • GetHashCode
  • Equals
  • ReferenceEquals
  • Finalize / ~Object()

 

객체의 비교

  • public virtual bool Equals(Object Obj) - 두 객체의 번지 비교
  • public static bool Equals(Object ObjA, Object ObjB) - 두 객체의 내용비교
  • public static bool ReferenceEquals(Object ObjA, Object ObjB) - 두 객체의 번지 비교

 

 

Reflection - 클래스나 객체의 타입 정보를 조사하는 기능 ex. Name, NameSpace, BaseType, IsAbstract, IsArray ...

클래스가 제공하는 정보는 전부 읽기 전용이고 타입정보를 얻는 방법은 세가지이다.

  1. Object의 GetType method 이용 ex Now.GetType()
  2. 정적 GetType 이용 ex. Type.GetType("Time")
  3. typeof 연산자 이용 ex. typeof(Time)

 

 

2.string Class

string 객체의 문자열은 읽기전용이다. 그래서 string의 메소드는 문자열 객체를 변경하는 것이 아니라 힙에 새로운 문자열을 만들어 리턴함을 주의하여야 한다.

ex. string str = "abcd";

      str.ToUpper()

의 경우 str이 "abcd"에서 "ABCD"로 바뀔 것 같지만 실제로 str은 그대로 이고 ToUpper()의 리턴값이 "ABCD"일뿐이다. 원래 문자열을 바꿀려면

ex. string str = "abcd";

      str =str.ToUpper();

로 수정해주어야 한다.

문자열을 수정하게 되면 문자열은 최초의 문자열이 변경되는 것이 아니라 메소드를 호출할때마다 새로운 문자열을 만들고 이전 문자열이 삭제되는 과정을 거치기때문에

매번 수정할때마다 힙상의 메모리 주소가 다르고 조작시 굉장히 비효율적이다. GC에도 부담이다. 잦은 문자열 조작에는 string builder를 사용해야 한다.

 

stringbuilder class

사용하는 방법은 string class와 유사하지만 메모리를 미리 할당해놓고 객체 자체를 조작하기때문에 훨씬 더 빠르다.

 

서식화

객체의 정보를 출력하기 위한 ToString을 보다 자세하고 원하는 방향으로 출력하기 위해서 ToString을 override해서 사용할수 있다. 또한 IFormatable 을 상속받아 locale정보까지 포함시켜 출력할수 있다.

 

정규식

검색식을 구성하는 문법을 규정하며 그 자체가 하나의 언어이다. Regex 클래스의 정적 메소드를 이용하여 사용할수 있다.

 

 

3.Collection - 변수들의 조직적인 집합이며 System.Collections의 파생클래스이다.

ArrayList - 정적인 Array와 달리  실행중 언제든지 크기를 확장, 축소할수 있는 동적 배열이다.저장되는 타입은 모든 타입이 가능하다. 여러개의 타입을 섞어 쓸수도 있다.

HashTable - 키와 값을 한쌍으로 저장하는 자료구조이다. 빠른 검색을 위해서 해쉬 알고리즘을 사용하였다. 해시란 자료의 고유한 해쉬값으로부터 저장할 위치를 선택하는 기법이다.

                 Equals과 GetHashCode를 재정의하여 고유의 객체 찾기를 할수 있다.

Stack / Queue

 

4.Utility class

DateTime - 날짜와 시간을 표현. 날짜는 특정한 시점을 나타내는데 두 날짜간의 간격을 표현할수 있는 클래스(TimeSpan)이 따로 있다. 이 클래스의 간격 정밀도는 천만분의 1초이다.

좀 더 짧은 시간을 측정하기 위해서는 Stopwatch라는 클래스도 있다.

Math - 수학함수들이 제공하는 클래스. 모든 메소드는 정적이다.

Environment - 이 클래스는 OS나 컴퓨터 시스템 또는 컴파일러 등에 대한 정보를 제공한다.

 

 

이 글은 스프링노트에서 작성되었습니다.

by 무위자연 2008. 8. 26. 09:23

닷넷프로그래밍정복 김상형저 가메출판사

...

이벤트

  1. 멀티캐스트 - delegate는 System.Delegate로부터 파생된 클래스이며 이 클래스의 객체는 하나의 메소드를 가르킬수 있다. 이 외에 둘 이상의 메소드를 가르킬수 있고 이것은 System.MulticastDelegate로부터 파생된다. 멀티캐스트 델리게이트는 여러개의 메소드를 등록할수 있는 목록을 가지고 있으며 등록된 순서대로 메소드를 호출하게 된다.
  2. 이벤트 - 어떤 사건이 발생했을때 호출되어야 하는 메소드의 목록이다. 내부적으로 멀티캐스트 델리게이트로 구현되며 사건 발생시 저장된 메소드를 순서대로 호출한다. 특정 사건이 발생할때마다 이 사건을 처리하고 싶다며 ㄴ이벤트에 호출할 메소드를 미리 등록해놓고 이 메소드에서 원하는 코드를 실행하면된다. 이벤트에 의해 호출되는 메소드를 특별히 이벤트 핸들러라 하고 관용적으로 EventHandler라는 이름을 사용한다.
  3.  익명 메소드 - 메소드는 일정한 선언 형식이 있기때문에 실제 작업을 하는 코드보다도 메소드의 헤더나 본체를 감싸는 블록이 소스를 더 많이 차지하며 작은 메소드들이 너무 많아지면 관리하기도 번거롭다. 또한 콜백 메소드나 이벤트 핸들러는 보통 특정한 상항에서 딱 한번만 호출되는 일회용이며 여러번 호출되지도 않아 반복제거의 의미도 없다. 이런 짧은 메소드에 이름붙이는 것조차 귀찮다. 그래서 익명메소드라는 것을 사용한다 . delegate 인자를 메소드 코드를 바로 넣는 것이다.

    ex.  delegate int dele(int a, int b)

           class CSTest

         {

    static void Main()

    {

    dele d = delegate (int a, int b) { return a + b};

    int k = d(2,3);

    }

    }

    여기서 익명메소드의 인수목록은 델리게이트의 인수목록과 정확하게 일치하거나 아예 인수목록이 없는 경우에 유효하다. 인수목록이 없는 경우 그 인수를 무시하고 정의한 함수는 가능하다.

     

이 글은 스프링노트에서 작성되었습니다.

by 무위자연 2008. 8. 26. 09:22

닷넷프로그래밍정복 김상형저 가메출판사

인터 페이스는 본체가 정의되지 않은 추상메소드를 가진 다는 것과 객체를 생성할수 없다는 점에서 추상클래스와 유사하다.

그러나 추상클래스는 추상메소드를 선택적으로 가지는데 비해 인터체이스의 메소드는 전부 추상이라는 점이 다르다.

 

연산자는 함수형 멤버이므로 이론적으로 인터페이스에 포함될수 있어야 한다. 하지만 C#은 비주얼 베이직과 호환성 문제로 인해

연산자를 인터페이스의 멤버에서 제외시켯다.

 

인터페이스의 멤버는 단순한 목록일뿐이므로 어떠한 지정자도 붙이지 않는다. 리턴타입과 목록같은 시그니쳐만 밝히면 된다.

 

상속에는 구현상속과 인터페이스 상속이 있다.

구현상속은 부모의 코드의 종속되어 버그까지 물여받을수 있는 단점이 있다.

인터페이스 상속은 구현코드는 물려받지 않고 구현해야 할 메소도의 목록만 상속받는 것인데, 종속성이 없고 내부구현에 상관없이 자신의 서비스를 외부에 노출시킬때 사용한다.

 

인터페이스간의 중간 상속이 가능하고 자식인터페이스는 부모의 인터페이스까지 목록에 가지고 있다.

하지만 C#은 다중상속은 지원하지 않는다. 효용보단 사용하기가 훨씬 까다로워서 삭제되었다. 굳이 원한다면 인터페이스를 다중상속한 다음에 구현해서 우회적으로 구현할수 있다.

 

다중 인터페이스 상속시 각기 다른 interface에서 같은 이름의 method가 있다면 하나만 구현하면 된다.

 

인터페이스 활용

1,IEnumerable과 EnumClass를 이용한 열거하기

2.IEnumerator의ㅏ GetEnumerator 메소드를 이용한 반복기.

3.ICloneable을 이용한 깊은 복사 - 참조만 복사하는 것을 얕은 복사, 대입에 의하 완전히 독립적인 생성하는 것을 깊은 복사라 한다.

 

메모리 관리.

1.가비지 콜렉터. - 백그라운드에서 항상 실행 중이며 더 이상 사용되지 않는 메모리, 즉 쓰레기를 찾아 회수한다. 그래서 개발자는 new 연산자로 필요한 만큼 객체나 메모리를 할당해서 쓰다가 그냥 나가 버리면 된다.

C#에는 delete라는 키워드가 없고 모두 GC에서 관리한다. 이런 특징은 일일이 할당한 메모리를 해제해야 하는 C++에 비해서 굉장히 편리할뿐 아니라 안전성도 높다. 자원해제를 위한 복잡한 제어구조를 만들지 않아도 되며 예외나 실수에 의해 메모리가 누출될 걱정따윈 필요없다. GC는 쓰레기 수집뿐 아니라 힙을 관리한다. 할당 요청이 있을때 힙의 낮은 번지부터 순서대로 할당하여 메모리를 깔끔하게 관리하는데 객체가 만들어지고 회수되기를 몇번 반복하면 힙의 중간중간이 비게 된다. 이런 현상을 단편화라고 한다. 이럴때 GC는 남아있는 메모리를 이동시켜 큰 덩어리를 만드는 Compaction을 수행한다. 큰 덩어리를 만들때 쓰레기를 수집하고 해제한 다음에 남은 객체들을 앞쪽으로 이동시켜 구획정리한다.

GC는 객체가 더 이상 필요하지 않을때 해제한다. 그렇다면 언제 객체가 필요하지 않다고 판단할까. 객체들은 보통 루트 객체 아래에 자식들이 계층적으로 존재하는 트리구조를 이룬다. 객체끼리 계층구조를 이룬다고 이해하면 되는데 더 정확하게는 상호참조가 가능하기때문에 그래프 구조라고 한다. GC는 루트객체로부터 순회를 시작하여 도달하지 않는 객체를 찾아 해제한다. GC는 세대를 관리해서 프로그램규모가 커져서 객체수가 늘었을때 검색시간이 늘었을때를 위해서 검색시간을 단축한다. 세대를 관리하는 이유는 최근에 만든 것일수록 쓰레기일 확률이 높고 오랫동안 살아남아 있다면 장시간에 걸쳐 사용되는 전역적인 객체일 확률이 높기때문이다. 높은 세대는 그만큼 점검을 자주할 필요가 없고 낮은 세대들만 가끔 점검해도 충분한 메모리를 손쉽게 확보할수 있다.

 

2.IDisponsable - GC는 충분히 정교하지만 관리자원만 관리한다. 메모리와 무관한 파일, 하드웨어 환경변화, 네트워크 접속 등은 GC가 관리하지 않기때문에 직접해줘야 한다. 이럴때 파괴자를 사용하여 객체가 사라질때 비관리 자원을 직접해제해야 한다. 일반적인 소멸자는 직접호출하는 것이 아니기때문에 자원해제 시점을 예측할수 없다. 그래서 IDisponsable interface가 필요하다.이 interface의 Dispose는 명시적으로 자원을 해제한다. GC를 기다리는 것이 아니라 수동으로 직접 해제함으로 불확실성이 사라진다.

ex. Socket Class example

class Socket : IDisposable
    {
        private int SocketPort;
        public Socket(int port)
        {
            SocketPort = port;
            Console.WriteLine("{0} 포트로 소켓을 연결한다", port);

        }
        public void Dispose()
        {
            SocketPort = 0;
            Console.WriteLine("소켓연결을 해제한다");
        }
    }

static void Main(string[] args)
        {
            Socket s = new Socket(1234);
            Console.WriteLine("주거나 받거나 통신했다 치고");

            s.Dispose();
        }

 

하지만 해당 클래스 사용자가 Dispose 호출을 잊을수 있다. 그렇다면 최소한의 방어로 소멸자 역시 구현해야 한다. 단순히 두 메소르를 그냥 만들어 놓는 것이 아니라 관리 자원과 비관리 자원을 적당히 나누어서 해제해야 하며 또한 이중 해제 하지 않도록 유의해야 한다.

ex) Socket class Example Extesion


 class Socket : IDisposable
    {
        private int SocketPort;
        private bool Disposed = false;
        public Socket(int port)
        {
            SocketPort = port;
            Console.WriteLine("{0} 포트로 소켓을 연결한다", port);

        }

        public void Dispose()
        {
            //SocketPort = 0;
            //Console.WriteLine("소켓연결을 해제한다");
            Dispose(true);
            GC.SuppressFinalize(this);
        }

        public virtual void Dispose(bool bManage)
        {
            if (Disposed) return;

            Disposed = true;

            if (bManage)
            {
                //여기서 관리 자원을 해제한다.
            }
            SocketPort = 0;
            Console.WriteLine("소켓연결을 해제한다");
        }

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

Dispose(bool)메소드가 하나 더 오버로드 되어 있는데 이 메소드는 bManage인수에 따라 모든 자원을 해제하거나 또는 비관리 자원만 해제한다. 코드의 중복을 방지하기 위해 실제 자원해제코드는 이 메소드에 작성되어 있고 소멸자와 Dispose()에서 이 메소드를 호출한다. Dispose(bool) 메소드는 고의 실수든 두번 이상 호출되더라도 이중 해제를 하지 않도록 한잔한 해제를 해야 해서 해제여부를 스스로 private field에 저장한다.

두개의 Dispose 메소드와 소멸자는 자원해제를 분담하는데 각 메소드는 호출되는 경로와 하는 역할이 다르다.

소멸자는 자신이 직접 할당한 비 관 리 자원만 해제해야 하며 관리자원을 해제해서는 안된다. 왜냐하면 소멸자가 GC에 의해 호출되는 시점이 예측할수 없고 아직 자원해제 되지 않는 객체가 이 객체를 참조하고 잇는 상황이 있을수 있기때문에 GC에 맡겨야 한다. 상속받은 Dispose()메소드는 Dispose(true)를 호출하여 관리 자원과 비 관리 자원을 모두 해제하야 객체가 생성되기 전의 상태로 완벽하게 복구하는 역할을 담당한다. GC.SuppressFinailize메소드는 GC가 이 객체의 소멸자를 부르지 않게 지시한다. Dispose에서 관리,비관리 자원을 모두 해제했으므로 소멸자를 호출할 필요가 없다. 만약 이 처리가 없다면 해제한 자원을 다시 해제하려고 할 것이다.

 

이 글은 스프링노트에서 작성되었습니다.

by 무위자연 2008. 8. 26. 09:20

닷넷프로그래밍정복 김상형저 가메출판사

C#은 닷넷 개발의 대표적인 언어이고 C/C++언어를 기반으로 만들어졌다. 엄밀하게는 C++ 강력함에 자바의 깔끔함과 VB의 편리함을 넣은 언어라 할수 있다.

특징은

  • 완전한 객체 지향언어
  • 단순하다 - 복잡도만 높이는 기능은 없다. ex 다중상속
  • 가비지 컬렉션 - 메모리 누수에 대한 문제 해결. 메모리 해제 문제에서 해방
  • 타입체크는 훨씬 엄격하게
  • 문법도 훨씬 엄격하게 - 암시적 변환도 경우에 따라 애러로 간주
  • 배열 경계를 점검하고 변수 오버플로우도 애러로 간주

그외에

  • 다중상속은 안되지만 인터페이스로 효과는 낼수 있다
  • 디폴트 인수 지원 없음
  • 클래스간의 프렌즈지정 안됨. 단 어셈블리끼리는 가능
  • 비트필드는 지원하지 않음
  • 기타 등등

 

구성요소

  • 주석은 한줄은 '//'  여러줄은 /**/으로 예외적으로 /// 다음에 XML형식의 주석을 작성하면 소스 문서화를 자동으로 할수 있다.
  • 대부분 C++과 유사.
  • 변수명에 @을 붙일수 있고, 유니코드로 변수 선언이 가능

 

연습은 p51-p61은 일단 스킵

이 글은 스프링노트에서 작성되었습니다.

by 무위자연 2008. 8. 26. 09:19

닷넷프로그래밍정복 김상형저 가메출판사

닷넷이 멀티 언어, 멀티 플랫폼을 지원할수 있는 것은 IL(혹은 CIL)과 JIT가 있기 때문에 가능하다.

닷넷 프로그램은 IL로만 컴파일되고 실행 직전에 플랫폼별 JIT 컴파일러에 의해 기계어 코드로 변환되어 실행된다.

 

닷넷의 구성요소

  • CLR(common Language Runtime) - JVM과 같은 개념. 어떤 언어로 만든 프로그램이던지 IL을 JIT로 컴파일한 다음에 CLR과 연결되므로 제작언어에 상관없이 CLR의 서비스를 받을수 있다.

    CLR은 닷네의 핵심 커널이다. 응용프로그램이 실행되면 CLR이 권한을 확인하고 프로세스를 생성하며 코드의 안전성을 검사한다. 보안 점검이 완료되면 첫번째 쓰레드를 생성하여 응용프로그램의 코드를 실행시킨다. 실행 중에 응영프로그램의 요청을 받아 때로는 직접 처리하기도 하고 때로는 호스트 운영체제와 통신을 주선하기도 한다. CLR은 운영체제와 닷넷의 응용프로그램 사이에 위차히며 한마디로 닷넷 프로그램 실행을 위한 모든 서비스를 제공하는 실행 주체이다.

  • CTS (Common Type System) - 모든 닷넹 언어들이 공동으로 사용하는 타입 체계를 정의한다.
  • CLS(Common Language Specification) - 닷넷이 정의한 언어들이 지켜야 하는 최소한의 사양.

    • 전역 함수나 변수는 정의할수 없다
    • 분호 없는 정수형은 인정하지 않는다
    • 명칭은 대소문자를 구분하지 않는다
    • 포인터를 사용할수 없다
    • 연산자 오버로딩을 지원하지 않는다.
  • BCL - 닷넷의 기본클래스 라이브러리

    • 기본 타입에 대한 정보 제공
    • 배열, 연결 리스트, 큐 등의 컬렉션 클래스
    • 그래픽 라이브러리(GDI++)
    • 스레드와 동기화 클래스
    • 각종 콘트롤
    • 파일 입출력
    • 네트워크와 인터넷프로그래밍
    • DB 억세스

 

닷넷의 장점과 단점은 닷넷은 자바를 보고 MS가 만들었다 라고 하면 명약관화해보인다. ㅋ

이 글은 스프링노트에서 작성되었습니다.

by 무위자연 2008. 8. 26. 09:17
| 1 2 3 4 |