객체지향프로그래밍 질문과 답

Console.Read()를 2번 사용하는 방법을 잘 모르겠습니다.

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

namespace BMI
{
    class Program
    {
        public static void Main(string[] args)
        {
            double H;
            double W;
            double B;
            string[] s = { "저체중", "정상", "과체중", "비만" };
            int i = 0;

            Console.Write("신장 : ");
            H = Console.Read();
            Console.Write("체중 : ");
            W = Console.Read();
            B = W / (H * H);

            if (B < 20) i = 0;
            else if (B >= 20 && B <= 24) i = 1;
            else if (B >= 25 && B <= 29) i = 2;
            else if (B >= 30) i = 3;

            Console.WriteLine("비만도 : {0:F}%", B);
            Console.WriteLine(s[i]);
        }
    }
}

위의 방법으로 프로그램을 실행시키면 신장을 입력 후 엔터키를 누르면

신장 : 177
체중 : 비만도 : 0.02%

라고 출력됩니다.

체중도 같이 입력하려면 어떻게 하면 되는지 잘 모르겠습니다.
교재의 143 쪽 또는 3 장 슬라이드의 28 쪽에 나옵니다만, Console.Read();는 하나의 문자를 읽어서 코드값으로 리턴하는 거지, 177같은 세자리 숫자를 읽어서 숫자로 리턴하는 메쏘드가 아닙니다. 따라서, 첫번째 Console.Read에서는 177이라는 입력에서 처음 문자인 '1'이 들어갔고, 다음 Console.Read에서는 두번째 문자인 '7'이 들어갔기 때문에 더이상 입력할 수 없는 겁니다.
원하는 대로 하시려면, double 값을 입력받으려고 하는 것이므로, Console.Read()를 double.Parse(Console.ReadLine()) 로 바꾸어야 합니다.
또한 입력을 177로 하셨는 데, 미터 단위로 입력해야 하므로 1.77 로 입력하시던지, 아니면 H 값을 센티미터로 얻고 나서 100으로 나누어야 할 것입니다.

for문과 foreach문에 대해서 배웠습니다. 충분히 for문으로도 할수 있는데, 굳이 foreach문을 만든 이유가 무엇인가요? 그리고 책에서는 for문보다 foreach문이 더 효율적이라고 하던데 어떤 면에서 효율적인가요?

굳이 foreach 문을 만든 건 프로그래머가 코딩하기 편하라고 그런 것입니다. 또한 완성된 프로그램 코드를 봤을 때에도 내용 상 더 명확함을 알 수 있습니다. 이러한 것들을 컴퓨터 언어에선 syntactic sugar 라고 합니다.
그리고 foreach 문은 for 문의 특별한 형태입니다. 배열이나 객체들을 가지고 있는 컨테이너를 처리하기 위해 만들어진, for 문의 특별한 한 형태로 볼 수 있습니다. foreach 문이 컴파일되어 결과적으로 생성하는 코드는 이러한 컨테이너들을 처리하게 위해 더 특화되어 있고 최적화되어 있습니다. for 문은 다양하고 foreach에 비해 더 일반적인 경우를 처리하기 위한 것이므로, 생성되는 코드도 foreach에서 생성되는 코드에 비해 더 일반적입니다. 따라서, 컨테이너들을 처리할 때에는 일반 for 문보다 더 효율적입니다.

C# 프로그램 실행 모델을 다시 설명해 주세요.

역시 1 장 강의 슬라이드의 30쪽에 있는 내용입니다.
C# 소스는 컴파일 단계가 되면 내부의 C# 컴파일러가 실행됩니다. MS가 제공하는 C# 컴파일러는 csc.exe 인데, 예를 들어 프레임워크 3.5가 있다면 C:\Windows\Microsoft.NET\Framework\v3.5 에 위치하고 있습니다. 이 csc.exe는 C# 소스를 받아서 exe 포맷의 파일을 만드는 데 .NET 구조에선 이 exe 파일도 어셈블리입니다. 이 exe 파일을 가지고 ildasm 이라는 명령으로 IL 언어로 기술된 소스 파일을 생성할 수 있습니다. 또한 ilasm 이라는 명령으로 역으로 IL 언어로 기술된 내용에서 exe 어셈블리를 생성할 수 있습니다.
이에 대한 설명은 1 장 강의 슬라이드의 31쪽에 있습니다.

.NET 프레임워크에서 언어의 종류와 상관없이 Assembly File을 만들면 실행이 된다고 하였는 데, 정확히 어떠한 의미인지 모르겠습니다.

MS에서 크게 치장했지만, 별로 심오한 얘기는 아닙니다.
설명드리자면, 어떤 언어건 그 데이터 타입이 .NET 프레임워크에서 지정한 공통 타입 스펙(Common Type Specification) 을 따르기만 하면, 이에 대해서 .NET 상에서 돌아가는 컴파일러를 만들 수 있습니다. .NET 상에서 돌아가는 그 컴파일러는 그 언어로 된 프로그램을 입력 받아 assembly file을 생성해 내는 데, 이 assembly file은 .NET IL이라는 특정한 중간 언어(와 메타데이터)로 되어 있습니다. 즉, .NET 상에서 돌아가는 컴파일러는, C건 C#이건 자바건 어떤 언어에 대한 컴파일러든지, 결국 .NET IL이라는 중간 언어로 기술된 어셈블리 파일을 생성하도록 .NET 프레임워크가 제한하고 있는 겁니다. 그러니 당연히 실행이 될 수 밖에 없는 겁니다. 알고보면 그리 대단한 건 아닙니다.
이러한 구조에 대한 그림은 1 장 강의 슬라이드의 30쪽에 있습니다.

책은 꼭 사야 합니까?

학비나 생활비를 아끼고 싶은 마음은 저도 이해합니다만, 본인이 C#을 잘 알고 있다고 자신하지 않는 한, 기본적으로 이런 정도의 교재는 필요합니다.
책을 사셔야 공부도 할 수 있지 않겠습니까?

다른 전공의 학생인데 불이익은 없는지요?

현재 학기에선 전혀 그럴 계획도 없고 아예 그런 생각은 하지 않고 있습니다.

이론 시험은 없습니까?

수업 시간에 말씀드렸지만 있습니다. 중간 시험을 이론 시험으로 볼 예정입니다. 기말시험은 교수가 지정한 프로그램을 개발하는 프로젝트로 대신합니다.

제 자바 실력은 아주 기초입니다. 자바를 최선을 다해 열심히 하겠습니다.

알겠습니다. 열심히 해주세요. 그런데, 본 강좌에서에는 C#을 강의하니까, C#도 열심히 해주시기 바랍니다.

자바에 대해 많이 잊어먹었습니다. 좀더 쉽게 설명해 주시기 바랍니다.

죄송합니다. 최대한 쉽게 설명하려고 합니다만 어렵네요.
네, 알겠습니다. 그런데, 혹시나 해서 다시 말씀드리지만, C#이 이번 학기의 주된 강의입니다.

콘솔/윈폼 어플리케이션에 대한 이해가 부족합니다.

다른 학생들의 질문들을 분석해 본 결과, 이미 알고 있는 학생들도 많으므로, 아는 친구에게 물어보던지 독학으로라도 빠르게 익숙해질 필요가 있다고 봅니다. 그렇지 않으면 많이 어려워질 것입니다.

VS2005을 써도 됩니까?

네. 비쥬얼 스튜디오 2005를 써도 됩니다.

비쥬얼 2008을 써도 됩니까?

네. 비쥬얼 스튜디오 2008입니다.

C++ 개발환경에서 C# 프로젝트를 생성해서 사용 가능합니까?

프로젝트를 마법사로 만들 때, C# 프로젝트를 선택할 수 있더군요.

C#과 같이 참고하면서 볼만한 책은 무엇이 있나요?

국내 서적은 홈페이지의 부교재에 이미 올렸습니다. "C#과 닷넷 플랫폼"과 "이펙티브 C#"은 필독하셔야 된다고 봅니다.

윈폼 쓰는 법은 계속 배웁니까?

교재를 보시면 아시겠지만, 그런 부분들이 꽤 됩니다. 앞으로도 계속 배우게 됩니다.

C# 강의를 자바 강의랑 같이 보는 게 좋은 방법입니까?

이건 배우는 학생이 어떻냐에 따라 다른 문제이지, 특별한 해답이 있는 게 아닙니다.
본인이 열심히 공부하거나 프로그램을 많이 짜보는 성격이 아니라면, 둘 다 같이 하지 말고, 하나의 언어를 하고 나서 다른 언어를 해보실 것을 권하고 싶습니다.

아까 화면 두 개를 말씀하셨는 데, 모니터 설정을 바꾸어 주면 가능할 수도 있습니다.

제 말은 두 개 이상의 프로젝터로 학생들에게 두 개 이상의 서로 다른 화면들을 보여주는 얘기였습니다.
두 개의 모니터를 사용하는 건, 요즘 운영체제에서는 그리 어렵지 않고, 개인적으로도 집에서 그렇게 쓰고 있습니다.

Vector와 matrix에 대해 설명해 주세요.

원래 vector는 1차원 배열을 의미하고, matrix는 2차원 배열을 의미하기도 합니다.
아마, 강의 중 1주차 강의 10쪽에 나온 것을 말씀하시는 거 같습니다. 배열 변수의 이름입니다.
변수의 이름을 짓는 건 프로그래머 본인 맘입니다.
물론 이것들이 변수의 이름이란 건 아셨을 거라고 봅니다.
만일 이것들이 변수의 이름이었다는 사실을 몰랐다면, 심각하게 프로그래밍 언어를 기초부터 공부하셔야 할 거 같습니다.

System에서 LINQ 형식을 인식하지 못한다고 나옵니다.

원인은 LINQ가 과거 2008 버전에서는 널리 사용되지 않았고, System 패키지 밑에 있는 것이 아니었기 때문입니다.
해결책은, 물론 LINQ는 매우 멋지고 중요한 개념입니다만, 아직 그리고 현재의 진도 속도를 볼 때 앞으로도, LINQ는 심각하게 배우지 않을 것이므로, 그냥 그 라인은 지우시면 됩니다.
그리고, 제가 수업 중에 말씀드렸는 데, 자동 생성되는 코드는 손으로 칠 필요가 없습니다.
화면에 나오는 코드를 무조건 다 그대로 치지 마시고, 제가 수업 중에 말씀드리는 것에 더 집중하셨다가 이 부분만 타이핑하라고 말씀드리는 부분만 타이핑 하면 됩니다.
프로그램을 손으로 쳐보는 시간은 따로 드리겠습니다.

클래스와 메쏘드를 사용하는 법을 가르쳐 주세요.

그건 앞으로 4장, 5장에서 배웁니다.
자바의 경우와 다를 게 없습니다.
미리 배우고 싶으면 독학으로 해보시던지, 실습 시간에 물어보시기 바랍니다.

프로퍼티와 델리게이트 개념을 좀 더 자세히 설명해 주세요.

프로퍼티와 델리게이트에 대한 자세한 내용은 앞으로 5장과 7장에서 각각 설명됩니다.
프로퍼티를 미리 잠깐 말씀드리자면, C# 클래스에서 마치 공개된 public 멤버 변수같이 보이지만, 내부적으로 getter/setter 메쏘드처럼 작동되는 기능입니다.
이에 대한 자세한 내용은 여기를 읽어 보시기 바랍니다.
델리게이트는 미리 잠깐 말씀드리자면, 메쏘드들을 참조할 수 있는 공간입니다.
이에 대한 자세한 내용은 여기를 읽어 보시기 바랍니다.

C#에서 static 을 사용할 때와 하지 않을 때의 차이는 무엇입니까?

Java의 경우도 동일하고, C++의 경우도 동일한 데, static은 정적인 바이딩(static binding)을 한다는 의미입니다.
프로그래밍에서의 경우, static으로 선언된 메쏘드는 객체를 인스턴스화하지 않고도 호출될 수 있고, static으로 선언된 멤버 변수도 객체를 새로 인스턴스화하지 않고도 사용이 가능합니다.
왜냐하면 static으로 선언되면 프로그램이 처음 실행될 때 이미 기억 장소에 그 자리가 확보되어 사용가능한 상태가 되기 때문입니다.
반면, new로 객체를 만드는 것은 동적으로 만드는 것으로 볼 수 있습니다.

이에 대한 자세한 내용은 여기를 읽어 보시기 바랍니다.

/// <summary> 와 /// </summary> 는 뭔지 궁금합니다.

Java, C++, C# 등의 언어들은 주석(커멘트)에서 문서화까지 지원합니다.
무슨 말이냐면, 프로그램을 작성할 때 이해를 돕기 위해 주석을 다는 데, 외부의 프로그램이 주석을 해석해서 매뉴얼이나 레퍼런스 가이드같은 책자까지 만들 수 있다는 것입니다.

Java의 경우는 문서화를 위한 대표적 프로그램이 JavaDoc입니다. 따라서 Java의 경우, JavaDoc 태그가 있습니다. JavaDoc을 위한 주석은 /** 로 시작합니다.

C#도 XML 형태로 문서화를 지원해 줍니다. C#에서는 /// 이 문서화를 위한 주석입니다.
<summary> 는 문서화를 위한 태그 중 하나로, 해당 개체에 대한 요약을 제공합니다.

이에 대한 자세한 내용은 여기를 읽어 보시기 바랍니다.

객체라는 것의 정확한 개념을 알려주세요.

원래 단순한 개념이 이해하기 어렵습니다. 따라서 이 질문은 간단하 대답될 수 있는 질문이 아닙니다. 예를 들면 사람이라는 것의 개념을 알려주세요라고 하면 쉽지 않을 것입니다.
하지만 억지로 간단히 대답하자면, 객체 지향 프로그래밍에서 객체에 대한 가장 간단한 해설은 멤버 데이터와 메쏘드들로 이루어져서 메모리를 차지하고 있는 (캡슐처럼 쌓여져 있는) 그 무엇인가라는 것이라는 겁니다.

클래스와 객체의 관계 말인데요. 붕어빵의 경우, 클래스의 인스턴스들인 거 같고요. 객체는 사람으로 치면 팔이나 다리같은 것들이 객체 아닌지요?

클래스가 인스턴스화가 되서 인스턴스가 생기면 그게 객체입니다.
좁은 의미의 객체입니다.
객체는 좁은 의미가 있고 넓은 의미가 있습니다.
예를 들어 사랑도 넓은 사랑이 있고, 좁은 의미가 있듯 객체도 그렇습니다.
그런데, 넓은 의미의 객체는, 우리가 흔히 일상생활에서 말하는 객체라는 것으로, 객체지향 프로그래밍에서 논의를 주고 받을 때 일반적으로 잘 안쓰입니다.

객체지향 프로그래밍에서 서로 논의를 주고 받을 때에, 객체라 함은 클래스의 인스턴스입니다.
클래스가 사람에 대한 일반적인 정의나 개념이라면, 개개인의 사람 하나하나는 객체입니다.
클래스가 붕어빵틀이라면, 붕어빵이 객체인 것입니다.
클래스가 자동차 설계도라면, 그 설계도로 만든 자동차는 객체입니다.
사람으로 치면 손, 발, 다리는 객체의 데이터 멤버 내지 필드라고 보시는 게 맞습니다.

OOP에서 가장 중요한 개념은 무엇인가요?

이것은 철학의 범주입니다. 따라서 사람마다 생각이 다를 수 있습니다.
제 생각엔, 그리고 대부분의 사람들 생각은, 추상화, 캡슐화, 정보은폐, 다형성, 상속 이라는 개념들입니다.
전적으로 개인적인 견해를 덧붙이자면, 객체지향설계에서 가장 피했으면 하는 특징은 상속입니다.
제 경험 상 상속은 가끔 가독성을 떨어뜨립니다. 즉 프로그램 코드를 읽기 어렵게 하더군요.
이에 대한 자세한 내용은 여기를 읽어 보시기 바랍니다.

OOP에서 디자인 패턴은 꼭 필요한 것인가요?

OOP에서 필요한 게 아니라, 프로그램 설계에서 필요한 것입니다. 디자인은 설계라는 뜻입니다. OOP와 연결되는 이유는 오늘날 새로운 소프트웨어 프로젝트의 대부분이 OOP 언어로 작성되고 있기 때문입니다.
패턴은 자주 등장하는 것을 의미합니다.
따라서, 디자인 패턴은 단순히 설계를 할 때 자주 등장하는 것을 말합니다.

자주 등장하는 것은 좋은 것이면 기억했다가 적용하고, 나쁜 것이면 기억했다가 피하면 됩니다.

디자인 패턴에 대한 책들을 보면, 설계 상에서 자주 등장하는 문제들과 이에 대한 해결책을 담고 있습니다.
주로 좋은 해결책들인데, 안티패턴(Anti-Pattern)이라는 책을 보면 나쁜 경우와 이에 대한 해결책이 나오기도 합니다.
사자성어로 말하자면 온고지신(溫故知新)이나 반면교사(反面敎師) 정도로 생각하시면 됩니다.
디자인 패턴은 온고지신, 안티패턴은 반면교사입니다.
여기를 보면 디자인 패턴에 대한 필독서가 나옵니다. 아쉽게도 절판되었습니다.

C#에서 프로퍼티는 언제 쓰는 것입니까?

프로퍼티에 대한 자세한 내용은 앞으로 5장에서 설명됩니다.
미리 잠깐 말씀드리자면, C# 클래스에서 마치 공개된 public 멤버 변수같이 보이지만, 내부적으로 getter/setter 메쏘드처럼 작동되는 기능입니다.
getter/setter 메쏘드를 설명하자면, 객체지향에서 데이터는 숨겨지고, 인터페이스만 공개됩니다.
따라서, 때에 따라 데이터를 주고 받기 위한 메쏘드가 필요해지는 데, 이 경우 사용되는 메쏘드들을 의미합니다.
이에 대한 자세한 내용은 여기를 읽어 보시기 바랍니다.
실제 사용되는가에 대해서 말씀드리자면, 프로퍼티가 뭔지 이미 알고 있고, 실제로 모 업체와의 프로젝트를 할 때 ASP.NET 과 C#을 통한 개발에서도 사용해 보았습니다만, 과연 필요한 것인지에 대해서는 개인적으로 의문입니다.
프로퍼티는 getter/setter 메쏘드와 데이터 멤버를 다룸에 있어 더 편리하게 해주는 것이라는 게 제 생각입니다.
이렇게 프로그래밍 문법 수준에서 뭔가 편리하게 해주는 것을 신택틱 슈거(syntactic sugar)라고 부르는 데, 프로퍼티도 그 중 하나입니다.

Console이 출력할 때 필요한 것입니까?

윈도우즈에서 보면, 과거 역사적인 이유로 인해, 프로그램은 텍스트 모드에서 실행될 수도 있고, 윈도우즈 GUI 응용 프로그램의 모습으로 실행될 수도 있습니다.
초기에는 텍스트 모드 밖에 없었지만, 20년 쯤 전부터 윈도우즈 GUI 응용 프로그램도 생겼습니다.
교재에는 안나오지만, 요즘은 스마트폰이 유행이라서, 실제로 스마트폰 모드도 추가되었습니다.

Console은 텍스트 모드에서 실행될 때, 입출력을 담당하는 부분을 가리키던 말입니다.
C#에서는 텍스트 모드의 입출력을 담당하는 클래스를 가리킵니다.

C#이 .NET에 최적화되었다고 하는 데, 그 이유는 무엇입니까? 어떤 부분에서 그러한지 설명해주세요.

간단히 말하면, 만든 데가 같은 회사이고 같은 시기에 거의 동시에 만들었습니다. (마이크로소프트)
마치 유닉스 운영체제와 C 언어와 비슷한 관계입니다. 유닉스 운영체제와 C 언어도 거의 동시에 같은 팀에서 만들었습니다.
최초의, 그리고 전세계의 대부분의 경우에 쓰이는 C# 컴파일러는 마이크로소프트가 .NET을 개발할 때 같이 만든 것을 계속 확장해 오고 있는 것입니다.
그러니 .NET에 최적화되었다고 주장할 수 밖에요.

그렇지 않고, 마이크로소프트가 주장하는 대로 설명하자면, C# 언어는 .NET의 Common Language Infrastructure (CLI)와 여러 면에서 유사합니다.
.NET 구조에서는 어떤 프로그래밍 언어든 .NET에서 요구하는 스펙들로 코드나 데이터만 생성하면 실행이 가능합니다.
그런데, C#의 내부 데이터 타입은 이미 원래부터 CLI 프레임워크의 것들과 매우 유사합니다.
이런 식으로 C#의 문법적인 부분들과 .NET의 구성 중 많은 부분이 동일합니다. 따라서, 최적화되어 있는 것이죠.

.NET이 뭐죠? 왜 C#과 같이 나오나요?

전적으로 제 관점에서 보면 자바와 그 버츄얼 머신(가상 기계)에 대한 MS의 복제물입니다. 물론 그 전에 스몰토크랄지 다른 버츄얼 머신 기반 언어들이 있었으므로 이 또한 논쟁의 여지가 있습니다만...

그 외의 .NET은 단순히 설명하자면 복잡한 여러 소프트웨어들로 구성된 하나의 구조입니다. 이런 경우, 프레임워크란 말을 씁니다.
이 .NET 소프트웨어 구조 위에서 C#으로 짠 프로그램들이 실행됩니다.
더 나아가 컴파일러가 .NET에서 요구하는 스펙만 따르면 어떤 언어로 만든 프로그램도 실행 가능합니다.
이에 대한 자세한 내용은 여기를 읽어 보시기 바랍니다.

닷넷이 C#과 같이 나오는 이유는 위의 "C#이 .NET에 최적화되었다고 하는 데, 그 이유는 무엇입니까? 어떤 부분에서 그러한지 설명해주세요. " 의 답에서 설명했습니다.