C# 2007/01/24 21:24

private 생성자..

나는 private로 만드는 생성자는 잘 쓰지 않는다. 글세 나만 잘 안쓰지 다른 사람들은 잘쓸지도 모르겠다. ^^ 백마디 말보다 소스 한번 보자~~

class PrivateConstruct
{
    private static PrivateConstruct privateConstruct = null;
    private int sumX;
    private int sumY;
    private PrivateConstruct()
    {
        Console.WriteLine("Private Construct~~");
    }
    public static PrivateConstruct getInstance()
    {
        if (PrivateConstruct.privateConstruct == null)
            PrivateConstruct.privateConstruct = new PrivateConstruct();
        return PrivateConstruct.privateConstruct;
    }
    public int Sum()
    {
        return (this.sumX + this.sumY);
    }
    public int i
    {
        get
        {
            return this.sumX;
        }
        set
        {
            this.sumX = value;
        }
    }
    public int j
    {
        get
        {
            return this.sumY;
        }
        set
        {
            this.sumY = value;
        }
    }
    static void Main(string[] args)
    {
        PrivateConstruct pc1 = PrivateConstruct.getInstance();
        PrivateConstruct pc2 = PrivateConstruct.getInstance();
        pc1.i = 1;
        pc1.j = 2;
        Console.WriteLine("pc1 의 sum() 메서드 " + pc1.Sum());
        Console.WriteLine("pc2 의 sum() 메서드 " + pc2.Sum());
    }
}



 

결과
Private Construct~~
pc1 의 sum() 메서드 3
pc2 의 sum() 메서드 3



위에서 PrivateConstruct 는 싱글톤 형태의 서비스를 한다. 싱글톤 서비스란 나는 웹서비스 쪽에서 처음 접했는데, 어떤 서비스를 요청할때 마다 매번 새로운 서비스를 만드는 것이 아니라, 딱 한번만 그 인스턴스를 만드는 것이다. 그래서 만든것을 가져다 사용 하는것이다. 그럼으로 이점은 숫자 카운팅이나 잊어버리지 않을 성격의 것들을 기억 할수 있다. 웹서비스가 멈출때까지...

그것을 구현하기 위해서 private 형으로 생성자를 선언했다. PrivateConstruct는 단 한개의 인스턴스만 있으면 된다. 뭐 위에 프로그램은 간단해서 문제가 없을지 모르겠지만, 만약 큰 통합 프레임워크 같은 경우에는 PrivateConstruct를 쓰게 된다면 어디선가 그냥 생성할수 있을것이다. 이것을 방지 하기위해서 private 생성자로 생성자을 만들어 놓으면 그냥 가져다 쓸경우 생성을 할수 없게 된다. 이런 경우 private 생성자를 사용하는것이 유용하게 쓰인다. ^^

흔히 쓰는 메모장 프로그램을 쓸때 쉽게 파일을 열수 있는 방법으로 빈 메모장 프로그램을 하나 실행시킨후 파일 탐색기에서 파일을 드래그 앤 드롭 하면 파일이 열리게 되고 텍스트 파일이나 기타 다른 파일들이 열리게 된다. 비단 메모장 프로그램 뿐만 아니라 한글이나 그림판 MS워드 등등등.. 수많은 프로그램들이 이런 기능들을 지원하게 된다. 그래서 한번 해보았다.

User inserted image
User inserted image


























다음과 같이 폼한개와 텍스트 박스 하나를 놓았다. 그 후 텍스트 박스의 AllowDrop 의 속성을 True로 바꾸어 주었다.



그리고 다음과 같은 소스를 이벤트를 추가하면 파일을 저장 할수 있다.

private void textBox1_DragDrop(object sender, DragEventArgs e)
{
    if (e.Data.GetDataPresent(DataFormats.FileDrop))
    {
        string[] file = (string[])e.Data.GetData(DataFormats.FileDrop);
        foreach (string str in file)
        {
            this.textBox1.Text += str + "\r" + "\n";
        }
    }
}
private void textBox1_DragEnter(object sender, DragEventArgs e)
{
    if (e.Data.GetDataPresent(DataFormats.FileDrop))
    {
        e.Effect = DragDropEffects.Copy | DragDropEffects.Scroll;
    }
}


다음과 같이 수정한 다음 파일을 드래그 해서 텍스트 파일 위에 올려 놓으면 파일명을 넘겨 받게 된다.

서버에서 TCP를 이용하여 파일을 하나 지정 받아서 대기 하고 있는다. 그런후 클라이언트에서 접속을 하게 되면 그 파일을 전송 받고, 클라이언트 프로그램에서는 파일을 받아 기록하게되는 간단한 소스 이다.

using System;
using System.Net;
using System.Net.Sockets;
using System.IO;
using System.Threading;
public class FileServer
{
private FileStream file;
private NetworkStream ns;
private IPAddress ipAddress;
private TcpListener listener;
private Thread sender;
private TcpClient client = null;
private long sendSize = 0;
public FileServer(string f)
{
 this.file = File.OpenRead(f);
 this.ipAddress = Dns.GetHostEntry("localhost").AddressList[0];
 this.listener = new TcpListener(ipAddress,3000);
 
 listener.Start();
 sender = new Thread(new ThreadStart(this.Acceping));
 Console.WriteLine("서버 실행중...");
 sender.Start();
}
~FileServer()
{
 file.Close();
}
public void Acceping()
{
 while(true)
 {
  client = listener.AcceptTcpClient();
  Console.WriteLine("클라이언트 접속");
  ns = client.GetStream();
  this.Send();
  ns.Close();
  client.Close();
 }
}
public void Send()
{
 byte[] b = new byte[1024];
 int count = 0;
 while( (count = this.file.Read(b,0,b.Length)) > 0 )
 {
  this.ns.Write(b,0,b.Length);
  this.sendSize += count;
 }
 Console.WriteLine("데이터 전송 완료");
}
public static void Main(string [] args)
{
 if( args.Length != 1)
 {
  Console.WriteLine("Usang args : AppName <fileName>");
  return;
 }
 if(!File.Exists(args[0]))
 {
  Console.WriteLine("File Access Error");
  return;
 }
 FileServer fServer = new FileServer(args[0]);
}
}


위의 코드를 실행 컴파일 시킨후 실행 시키게 된다. 그리고 다음은 클라이언트 소스 프로그램이다.

using System;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Threading;
public class Client
{
private TcpClient client;
private NetworkStream ns;
private FileStream fs;
private Thread receive;
public Client(string ipAddress)
{
 this.client = new TcpClient(ipAddress,3000);
 this.ns = client.GetStream();
 this.fs = new FileStream("get.dat" , FileMode.Create);
 receive = new Thread(new ThreadStart(this.Receive));
 receive.Start();
}
public void Receive()
{
 int count = 0;
 byte[] b = new byte[1024];
 while( (count = ns.Read(b,0,b.Length))>0)
 {
  fs.Write(b,0,b.Length);
 }
 Console.WriteLine("파일전송완료");
}
~Client()
{
 fs.Close();
 ns.Close();
 client.Close();
}
public static void Main(string[] args)
{
 Client cl = new Client(args[0]);
}
}

C# 2007/01/13 13:11

파일 카피 프로그램..

바이너리 형태로 파일을 읽어 들여 복사하는 프로그램이다. 카피 할때 스레드를 이용해서 복사를 하였고, 닷넷에서 지원해 주는 카피 매서드는 이용하지 않고 구현해 보았다.

using System;
using System.IO;
using System.Text;
using System.Threading;
public class BCopy
{
private string originalFile;
private string copyFile;
private FileStream rs = null;
private FileStream ws = null;
private long fileSize = 0;
public BCopy(string ofile,string cfile)
{
 this.originalFile = ofile;
 this.copyFile = cfile;
 try
 {
  this.rs = File.OpenRead(this.originalFile);
  this.ws = new FileStream(this.copyFile,FileMode.Create);
 }
 catch (Exception e)
 {
  Console.WriteLine(e.Message);
 }
}
~BCopy()
{
 rs.Close();
 ws.Close();
}
public void Copy()
{
 try
 {
  byte[] b = new byte[1024];
  int count = 0;
  while( (count = rs.Read(b,0,b.Length)) > 0)
  {
   ws.Write(b,0,count);
   this.fileSize += count;
  }
 }
 catch (Exception e)
 {
  Console.WriteLine(e.Message);
 }
 finally
 {
  Console.WriteLine("File size : " + this.fileSize);
 }
}
public static void Main(string[] args)
{
 if( args.Length != 2)
 {
  Console.WriteLine("Usang Args : app <orginal Filename> <copy Filename>");
  return;
 }
 try
 {
  BCopy fileCopy = new BCopy(args[0],args[1]);
  Thread copyThread = new Thread(new ThreadStart(fileCopy.Copy));
  copyThread.Start();
 }
 catch (Exception e)
 {
  Console.WriteLine(e.Message);
 }
}
}



솔직히 별로 한것은 없고 읽은것을 쓰는데 하는것을 좀 오래 찾았아 ㅡ.ㅡ;

MySql OleDb 를 사용하여 데이터 베이스에 데이터를 넣는 간단한 프로그램을 작성하였다.

using System;
using System.Data;
using System.Data.OleDb;
public class App
{
public static void Main()
{
string conStr = "Provider=MySQLProv;Data Source=csharp;" +
     "Location=localhost;User Id=root;Password=apmsetup";
string insert = "Insert into Address values(1,'김병수','서울')";
OleDbConnection conn = new OleDbConnection(conStr);
conn.Open();
OleDbCommand insertComm = new OleDbCommand(insert,conn);
insertComm.ExecuteNonQuery();
conn.Close();
}
}



위와 같은 프로그램을 작성 하고, 컴파일을 하였다. 아무 에러 없이 컴파일이 되었고 실행을 시켜 보니 다음과 같은 에러가 발생 했다.

처리되지 않은 예외: System.Data.OleDb.OleDbException: 오류 메시지 없이 'MySQLPro
v'이(가) 실패했습니다(결과 코드: E_FAIL(0x80004005)).
  위치: System.Data.OleDb.OleDbCommand.ExecuteCommandTextForSingleResult(tagDBP
ARAMS dbParams, Object& executeResult)
  위치: System.Data.OleDb.OleDbCommand.ExecuteCommandText(Object& executeResult
)
  위치: System.Data.OleDb.OleDbCommand.ExecuteCommand(CommandBehavior behavior,
Object& executeResult)
  위치: System.Data.OleDb.OleDbCommand.ExecuteReaderInternal(CommandBehavior be
havior, String method)
  위치: System.Data.OleDb.OleDbCommand.ExecuteNonQuery()
  위치: App.Main()



일단 에러가 처리 되어서 무슨 에러인지 위의 메세지를 봤을때 잘몰르겠다. ^^;; 심각히 고민해 보다가 쿼리문에 잘못이 있나 하여서 한번 쿼리 문을 직접 sql문에다 실행을 시켜 보았는데 이게 왠걸 입력이 잘된다....

그렇다면 무슨 문제가 있는것이라는 얘기인데 이리 저리 궁리해 보다가 문제점을 찾았다. 소스를 아래와 같이 수정 하였다.

using System;
using System.Data;
using System.Data.OleDb;
public class App
{
public static void Main()
{
 string conStr = "Provider=MySQLProv;Data Source=csharp;" +
     "Location=localhost;User Id=root;Password=apmsetup";
 string insert = "Insert into Address values(1,'KimByoungSoo','Seoul')";
 OleDbConnection conn = new OleDbConnection(conStr);
 conn.Open();
 OleDbCommand insertComm = new OleDbCommand(insert,conn);
 insertComm.ExecuteNonQuery();
 conn.Close();
}
}



위와 같이 입력을 하고 실행을 시켜 보니 아무런 예외 처리가 나오지 않았고 sql을 검색 해보니 잘 들어가 있었다.

mysql> select * from address;
+------+--------------+--------+
| id      | name              | addr   |
+------+--------------+--------+
|    1    | 김삿갓             | 서울시 |
| NULL | NULL              | NULL   |
| NULL | NULL              | NULL   |
| NULL | NULL              | NULL   |
|    1    | 1                    | 1      |
| NULL | NULL              | NULL   |
|    1    | KimByoungSoo | Seoul  |
|    1    | KimByoungSoo | Seoul  |
+------+--------------+--------+
8 rows in set (0.00 sec)



그렇다면 문제점은 한글전송시 문제가 발생한다는 것이다. 음.. 이것을 해결할 방법은..... 찾아 봐야 겠다.

C# 2007/01/09 11:40

XML 정보 읽기

XML 관련 클래스를 가지고 본 블로그의 RSS의 데이터를 한번 읽어 보기 위해 시도 해보았다. XML의 두가지 형태 접근으로 순차 접근과 트리 접근이 있다. 그 방식중 일단 순차적으로 한번 읽어 보았다.

using System;
using System.Xml;
public class App
{
public static void Main()
{
XmlTextReader tr = new XmlTextReader("http://hahakbs.dothost.co.kr/rss");
while(tr.Read())
{
  if(tr.NodeType == XmlNodeType.Text)
   Console.WriteLine(tr.Value);
}
tr.Close();
}
}



위와 같은 소스로 병수 블로그의 RSS를 읽어 보았다 결과는 성공 결과물은 너무 길어서 생략 하겠슴..

그렇다면 트리형식의 접근 방법인 DOM 방식의 클래스 XMLDocument을 사용하여 한번 접근 해보았다.

using System;
using System.IO;
using System.Xml;
public class App
{
public static void Main()
{
XmlTextReader tr = new XmlTextReader("http://hahakbs.dothost.co.kr/rss");

XmlDocument xdoc = new XmlDocument();
xdoc.Load(tr);
DisplayTree(xdoc.DocumentElement);
tr.Close();
}
public static void DisplayTree(XmlNode node)
{
if(!node.HasChildNodes)
  Console.WriteLine(node.Value);
else
  Console.WriteLine("<" + node.Name + ">");
if(node.HasChildNodes)
{
  node = node.FirstChild;
  while(node != null)
  {
   DisplayTree(node);
   node = node.NextSibling;
  }
}
}
}



접근이 잘되었다. 위의 방법도 결과가 너무 길어 생략. 각 노드들을 보여 줄때는 재귀적인 방법으로 접근하여 모든 노드들을 접근하였다.  접근이 잘 되었다.

그렇다면 이번에는 검색해서 그 검색 결과를 한번 표현해 보겠다.

using System;
using System.Xml;
using System.Xml.XPath;
public class App
{
public static void Main()
{
XPathDocument doc = new XPathDocument("http://hahakbs.dothost.co.kr/rss");
XPathNavigator nav = doc.CreateNavigator();
XPathNodeIterator iter = nav.Select("rss/channel/item/title");
while(iter.MoveNext())
  Console.WriteLine(iter.Current.Value);
}
}



결과

XML 이란..
Aspect Oriented Programming
Delegate를 함수의 매개변수로 넘기기
Visual Studio 사용하지 않고 Winform 만들기
애트리뷰트(Attribute)들.
catch 블럭과 finally 블럭 안에서의 예외처리는?
2006년 내머리속에는..
인덱서(Indexer)
오버라이딩의 두가지 방법
internal과 protected internal



위의 소스는 블로그의 타이틀만을 검색해서 검색결과를 출력해주는 간단한 프로그램을 작성 하였다. 검색은 이와 다른 매치 기능등이 있는데 그것들은 귀찮아서 생략 ^^;;


Thread thread2 = new Thread(ts2);
 



스레드클래스를 생성 시킬때 생성자에 ts2 라는 놈은 델리게이트이다. 그렇다면 매개변수로 델리게이트를 넘겨 받아 쓸수 있다는 소리 인데 한번 해보기로 했다.

소스


using System;
delegate void TestDelegate();
public class Temp
{
public void Test()
{
Console.WriteLine("테스트 함수");
}
public void ReceiveDele(TestDelegate ts)
{
Console.WriteLine("델리게이트 매개변수 받기");
}
}
public class TempApp
{
public static void Main()
{
Temp t = new Temp();
TestDelegate tdele = new TestDelegate(t.Test);
tdele();
t.ReceiveDele(tdele);
}
}
 


위와 같은 소스를 작성 하고 컴파일을 해보았다. 그런데 결과는??

Microsoft (R) Visual C# 2005 Compiler version 8.00.50727.42
for Microsoft (R) Windows (R) 2005 Framework version 2.0.50727
Copyright (C) Microsoft Corporation 2001-2005. All rights reserved.

TestDele2.cs(11,14): error CS0051: 일관성 없는 액세스 가능성: 'TestDelegate' 매개 변수 형식이 'Temp.ReceiveDele(TestDelegate)' 메서드보다 액세스하기 어렵습니다.
TestDele2.cs(3,15): (이전 오류와 관련된 기호 위치)


위와 같았다. 이게 뭔소리여? 어째던 에러 보통의 방법으로는 안된다는 얘기이다. 음.. 그렇다면 단순한 나의 생각으로는 evet로 만들어서 넘겨 줘야 하나?? 다음과 같이 수정하였다.


public void ReceiveDele(event TestDelegate ts)
{
Console.WriteLine("델리게이트 매개변수 받기");
}
 


다음과 같이 수정을 하고 이번에 컴파일을 해봤다.

Microsoft (R) Visual C# 2005 Compiler version 8.00.50727.42
for Microsoft (R) Windows (R) 2005 Framework version 2.0.50727
Copyright (C) Microsoft Corporation 2001-2005. All rights reserved.

TestDele2.cs(11,26): error CS1031: 형식이 필요합니다.
TestDele2.cs(11,47): error CS1002: ;이 필요합니다.
TestDele2.cs(13,20): error CS1519: 클래스, 구조체 또는 인터페이스 멤버 선언에
       잘못된 '(' 토큰이 있습니다.
TestDele2.cs(15,1): error CS1022: 형식이나 네임스페이스 정의 또는 파일 끝(EOF)이
       필요합니다.


역시 이번에도 에러가 났다. 흠... 과연 할수 없는 것인가? 안쓰던 머리를 굴리기 시작 했다. 과연 어떤 방법으로 넘겨 줄 것인가? 분명 스레드 객체를 생성 할때 분명히 델리게이트 자체를 넘기는 것은 확실했다. 분명히 방법은 있다. 그렇지만 내가 못하는것 뿐. 그래서 한번 System.Threading 에 관한것을 MSDN에서 찾아 보았다. 그런데 그부분에 관해서는 나와 있지 않았다.

그런데 갑자기 불현듯 스쳐간 생각이 떠올랐다. 모든 변수나 객체들은 object형을 상속 받는다는 생각. 그렇다면 object형으로 넘겨 받으면 가능할지도 모른다는 생각 그래서 다음과 같이 소스를 수정하였다.


using System;
delegate void TestDelegate();
public class Temp
{
public void Test()
{
Console.WriteLine("테스트 함수");
}
public void ReceiveDele(object ts)
{
TestDelegate Receive = (TestDelegate) ts;
Console.WriteLine("델리게이트 매개변수 받기");
Receive();
}
}
public class TempApp
{
public static void Main()
{
Temp t = new Temp();
TestDelegate tdele = new TestDelegate(t.Test);
tdele();
t.ReceiveDele(tdele);
}
}
 


결과는

테스트 함수
델리게이트 매개변수 받기
테스트 함수


성공이였다. 처음으로 객체지향적으로 생각을 해보았다. ^^ 앞으로 머리 많이 굴려야 될거 같다.

될줄은 알았는데 상당히 많은 것을 써줘야 될거 같았다. 그런데 예상외로 간단하였다.

소스


using System;
using System.Windows.Forms;
public class App : Form
{
 public App()
 {
  this.Click += new EventHandler(AppMouseClick);
 }
 private void AppMouseClick(object obj,EventArgs e)
 {
  MessageBox.Show("안녕");
 }
}
class MyApp
{
 public static void Main()
 {
  Application.Run(new App());
 }
}
 


일단 어플리케이션 클래스에 Form 클래스를 상속 받고 Main이 있는 클래스에서 Application.Run을 에 상속 받은 클래스를 생성시키면 간단하게 Winform이 완성 되고 그곳에 폼에서 클릭을 받을수 있는 이벤트 핸들러를 구현한 다음 Click 이벤트에다 등록을 시켜서 클릭을 하면 MessageBox가 띄워지게 된다. 이벤트 핸들러를 작성하고 싶지 않으면 App클래스의 내용을 다지워서 컴파일 하여도 작동이 잘된다.

결과

User inserted image

보면 항상 궁금 했던 부분이였다. 클래스의 선언전에 [] 안에 넣는 것들은 무엇에 쓰고 왜쓰이나? 그리고 단어도 길어서 항상 어려워 보였다.

[Attribute()]      컴파일시에 CLR에 등록해주는 클래스로서 메타데이터이다.
[Conditional()] 조건부 함수를 만들때 사용된다. 함수 호출을 제어할 수 있다.
[Obsolete()]     더 이상 사용하지 않는 요소를 표시한다. 컴파일시 경고 메세지를 출력.
[DllImport()]     기존에 만들어진 외부 DLL을 호출하기 위해 사용.


[Attribute()] 는 Attribute나 Attribute의 클래스를 상속받은 클래스를 가지고 컴파일 시에 선언된 클래스나 메서드에 첨부된 후 메모리에 등록된다.

보기


[Conditional()] 특정 전처리 식별자에 이해 실행되는 조건부 함수의 호출을 제어 할수 있다. 쉽게 #define 심볼의 유무에 따라서 호출이 결정된다.

보기


[Obsolete()] 더 이상 사용하지 않는 프로그램 요소를 표시 한다. 이 속성의 함수를 실행할 시에는 경고 컴파일시 경고 메세지를 받게 되나 컴파일은 수행된다.

보기


[DllImport()] 기존에 만들어진 외부 DLL을 호출하기 위해서 사용하는 애트리뷰트이다.

보기

프로그램이 어떠한 예외가 발생하게 되면 비정상적인 동작을 하게 된다. 그래서 프로그램이 끝나거나 이상한 동작을 수행 하는데, 이것을 방지 하기 위해서 예외처리를 해준다. try,catch,finally 응 이용해서.

try : 예외가 발생할만한 의심 스러운 코드를 try구문안에 넣어준다.
catch : 예외가 발생되면 그 발생된 예외를 받아 처리 하는 부분이다.
finally : 예외가 발생되든 되지 않던 무조건 처리 하는 부분이다.



위에것은 일반적인 사실이다. 그런데 참 우수운것 같다. 일부러 발생시킨 예외를 제외하고 누가 예외 날것을 알고 프로그램을 하는가? 그렇지만 그래도 모를 예외에 관련 되서 try구문을 사용한다고 봤을때 혹시 또 누가 알것인가? 예외처리를 잡아주려고 한 catch 문에 또 예외가 발생한다면? 아니면 무조건 처리 하는 부분에서의 finally 에서의 예외가 발생한다면? 두가지 상황을 알아 보았다.

일반적인 예외 발생 소스

using System;
public class ExceptionInCatch
{
 public static void Main()
 {
  string s = null;
  try
  {
   Console.WriteLine("try 문 \n예외 발생");
   Console.WriteLine(s.ToString());
  }
  catch
  {
   Console.WriteLine("catch 문");
  }
  finally
  {
   Console.WriteLine("finally 문");
  }
 }
}
 


결과

try 문
예외 발생
catch 문
finally 문



다음과 같은 간단한 예외를 발생시켜 보았다. 이제 catch 구문 안에 예외를 발생 시켜 보겠다.

수정 부분

  catch
  {
   Console.WriteLine("catch 문");
   Console.WriteLine(s.ToString());
  }
 



결과
일반 예외 처리를 안한 것처럼 다음과 같은 결과가 나왔다.

try 문
예외 발생
catch 문

처리되지 않은 예외: System.NullReferenceException: 개체 참조가 개체의 인스턴스로 설정되지 않았습니다.
  위치: ExceptionInCatch.Main()
finally 문



그렇다면 finally 구문 안에서의 예외는?

수정부분

  finally
  {
   Console.WriteLine("finally 문");
   Console.WriteLine(s.ToString());
  }
 



결과
catch문에서와 비슷한 결과가 나오게 되었다.

C:\Test\C#>ExceptionInCatch
try 문
예외 발생
catch 문
finally 문

처리되지 않은 예외: System.NullReferenceException: 개체 참조가 개체의 인스턴스로 설정되지 않았습니다.
  위치: ExceptionInCatch.Main()


그렇다면 사람이 신도 아니고 catch나 finally 안에서 나는 Exception의 처리는 어떻게 해야 하나?

방법은 아주 간단 하였다. catch 안이나 finally 안에서 또 try,catch,finally 를 쓰면 그 안에서 난 예외도 다시 처리할수 가 있었다.


using System;
public class ExceptionInCatch
{
 public static void Main()
 {
  string s = null;
  try
  {
   Console.WriteLine("try 문 \n예외 발생");
   Console.WriteLine(s.ToString());
  }
  catch
  {
   Console.WriteLine("catch 문");
   try
   {
    Console.WriteLine(s.ToString());
   }
   catch
   {
    Console.WriteLine("catch문 안에서의 예외처리");
   }
  }
  finally
  {
   Console.WriteLine("finally 문");
   try
   {
    Console.WriteLine(s.ToString());
   }
   catch
   {
    Console.WriteLine("filally문 안에서의 예외처리");
   }
  }
 }
}
 


결과

C:\Test\C#>ExceptionInCatch
try 문
예외 발생
catch 문
catch문 안에서의 예외처리
finally 문
filally문 안에서의 예외처리


결론은 글세 뭐 catch에서의 Exception 등의 예외는 다시 그 안에 try구문을 사용하여 다시 처리 할수 있다. 라는 짤막한 결론이 나왔다.


div>