/*1. SQLite를 설치한(Install) 후에
2. SQLite DLL을 프로젝트에 참조한 후에*/

using System;
using System.Data.SQLite;

class Program
{
public static void Main()
{
SQLiteManageCls nm = new SQLiteManageCls();
nm.running();
}
}

class SQLiteManageCls
{
string connectionString = "Data Source=:memory:"; 
SQLiteConnection sqliteConnection = null; 
SQLiteCommand sqliteCommand = null;

public void running()
{
try 

sqliteConnection = new SQLiteConnection(connectionString); 
sqliteConnection.Open(); 
string sql = "SELECT SQLITE_VERSION()"; 
sqliteCommand = new SQLiteCommand(sql, sqliteConnection); 
string version = sqliteCommand.ExecuteScalar().ToString(); 
Console.WriteLine("SQLite version : {0}", version); 
}
catch(SQLiteException sqliteException) 

Console.WriteLine("Error: {0}", sqliteException.ToString()); 

finally 
{
if(sqliteCommand != null) { sqliteCommand.Dispose(); }
if(sqliteConnection != null) 
{
try 

sqliteConnection.Close(); 

catch(SQLiteException sqliteException) 

Console.WriteLine("Closing connection failed."); 
Console.WriteLine("Error: {0}", sqliteException.ToString()); 

finally 

sqliteConnection.Dispose(); 
}
}
}
}
}

/*c# *.DLL IDE에 추가하기*/

새로운 using 구문을 사용하기 위해서 예를들어서 using System.Data.SQLite;


DLL을 함께 추가해줘야 한다. 

1. Visual Studio(IDE)에서

2. Project 트리에서

3. 참조

4. 참조추가

5. 찾아보기로 해당 DLL을 클릭후에 확인(full path)

빌드후에 정상적으로 실행이 되는지 확인한다.

SQLite을 설치한 후에 C# 프로젝트에서 System.Data.SQLite.dll를 참조한 후 using System.Data.SQLite; 네임스페이스를 참조하면, SQLite의 .NET 클래스들 (예: SQLiteConnection, SQLiteCommand, SQLiteDataReader 등)을 사용할 수 있다.

using System;  
using System.Collections.Generic;  
using System.Net;  
using System.Net.Sockets;  
using System.IO;  
using System.Text;  
 
namespace FileTransfer  
{  
    class Program  
    {  
        static void Main(string[] args)  
        {  
            // Listen on port 31234    
            TcpListener tcpListener = new TcpListener(IPAddress.Any, 31234);  
            tcpListener.Start();  
 
            Console.WriteLine("Server started");  
 
            //Infinite loop to connect to new clients    
            while (true)  
            {  
                // Accept a TcpClient    
                TcpClient tcpClient = tcpListener.AcceptTcpClient();  
 
                Console.WriteLine("Connected to client");  
 
                StreamReader reader = new StreamReader(tcpClient.GetStream());  
 
                // The first message from the client is the file size    
                string cmdFileSize = reader.ReadLine();  
 
                // The first message from the client is the filename    
                string cmdFileName = reader.ReadLine() + "_1";  
 
                int length = Convert.ToInt32(cmdFileSize);  
                byte[] buffer = new byte[length];  
                int received = 0;  
                int read = 0;  
                int size = 1024;  
                int remaining = 0;  
 
                // Read bytes from the client using the length sent from the client    
                while (received < length)  
                {  
                    remaining = length - received;  
                    if (remaining < size)  
                    {  
                        size = remaining;  
                    }  
 
                    read = tcpClient.GetStream().Read(buffer, received, size);  
                    received += read;  
                }  
 
                // Save the file using the filename sent by the client    
                using (FileStream fStream = new FileStream(Path.GetFileName(cmdFileName), FileMode.Create))  
                {  
                    fStream.Write(buffer, 0, buffer.Length);  
                    fStream.Flush();  
                    fStream.Close();  
                }  
 
                Console.WriteLine("File received and saved in " + Environment.CurrentDirectory);  
            }  
        }  
    }  

using System;  
using System.Collections.Generic;  
using System.Net;  
using System.Net.Sockets;  
using System.IO;  
using System.Text;  
 
namespace FileTransferClient  
{  
    class Program  
    {  
        static void Main(string[] args)  
        {  
            try  
            {  
                Console.WriteLine("Please enter a full file path");  
                string fileName = Console.ReadLine();  
 
                TcpClient tcpClient = new TcpClient("127.0.0.1", 31234);  
                Console.WriteLine("Connected. Sending file.");  
 
                StreamWriter sWriter = new StreamWriter(tcpClient.GetStream());  
 
                byte[] bytes = File.ReadAllBytes(fileName);  
 
                sWriter.WriteLine(bytes.Length.ToString());  
                sWriter.Flush();  
 
                sWriter.WriteLine(fileName);  
                sWriter.Flush();  
 
                Console.WriteLine("Sending file");  
                tcpClient.Client.SendFile(fileName);  
 
            }  
            catch (Exception e)  
            {  
                Console.Write(e.Message);  
            }  
 
            Console.Read();  
        }  
    }  

/*
전제:TCP/IP의 중요한 성질

5. Flow control
송신자는 수신자가 받을 수 있는 만큼 데이터를 전송한다. 
수신자가 자신이 받을 수 있는 바이트 수 (사용하지 않은 버퍼 크기, receive window)를 송신자에게 전달한다. 
송신자는 수신자 receive window가 허용하는 바이트 수만큼 데이터를 전송한다.
*/

case1)
send:A0011,,,,,,(500byte)
recv:A0011,,,,,,(500byte)
send:A0011,,,,,,(500byte)
recv:A0011,,,,,,(500byte)
send:A0011,,,,,,(500byte)
recv:A0011,,,,,,(500byte)

case2)
send:A0011,,,,,,(500byte)
send:A0011,,,,,,(500byte)
send:A0011,,,,,,(500byte)
recv:A0011,,,,,,(500byte) * 3

How to process such a case(?)
위의 2가지 조건을 모두 충족시킬수 있도록 서버측에서 프로그램이 구현되어야 할것이다.

TCP/IP
transmission control protocol/Internet protocol 

네트워크 간 전송 제어 프로토콜.
서로 다른 시스템을 가진 컴퓨터들을 서로 연결하고, 데이터를 전송하는 데 사용하는 통신 프로토콜들의 집합

 

데이터 전송

 

데이터 수신

 

스택 내부 제어 흐름(control flow)

 

인터럽트와 수신 패킷 처리

 

데이터 구조체

TCP control block

 

드라이버와 NIC의 통신

 

패킷 전송 과정을 따라가며 링을 어떻게 사용하는지 알아보자.

 

 패킷 수신 과정을 볼 수 있다.

 

 

스택 내부 버퍼와 제어 흐름(flow control)

 

 

 

 

 

 

성능 이해와 현상 분석을 하기 위해 운영체제의 TCP/IP 관련 코드 한 줄 한 줄을 모두 이해하고 있을 필요는 없다. 큰 흐름만 알고 있어도 많은 도움이 된다.

https://d2.naver.com/helloworld/47667

 

 

nohup 명령어는 리눅스에서 프로세스를 실행한 터미널의 세션 연결이 끊어지더라도 지속적으로 동작 할 수 있게 해주는 명령어입니다.

코드에 줄 번호 표시
메뉴 모음에서 도구 > 옵션 을 차례로 선택합니다. 텍스트 편집기 노드를 확장한 다음, 사용 중인 언어나 모든 언어 를 선택하여 모든 언어에 줄 번호를 켭니다. (또는 검색 상자에 줄 번호 를 입력하고 결과에서 줄 번호 설정/해제 를 선택합니다.)

줄 번호 확인란을 선택합니다.

참고>
줄 번호는 코드에 추가되지 않으며 참조용으로만 사용됩니다.

 

/*
ToInt32(String) 의 예외처리

예외
FormatException
value가 선택적 부호와 숫자 시퀀스(0~9)로 구성되어 있지 않습니다.

OverflowException
value은(는) MinValue보다 작거나 MaxValue보다 큰 숫자를 나타냅니다.
*/
/*
//오버로드//오버로드//오버로드//오버로드//오버로드//오버로드//오버로드//오버로드//오버로드//오버로드
ToInt32(String)
숫자의 지정된 문자열 표현을 해당하는 32비트 부호 있는 정수로 변환합니다.

ToInt32(UInt16)
지정된 16비트 부호 없는 정수의 값을 해당하는 32비트 부호 있는 정수로 변환합니다.

ToInt32(UInt32)
지정된 32비트 부호 없는 정수의 값을 해당하는 32비트 부호 있는 정수로 변환합니다.

ToInt32(Single)
지정된 단정밀도 부동 소수점 숫자 값을 해당하는 32비트 부호 있는 정수로 변환합니다.

ToInt32(Object, IFormatProvider)
지정된 문화권별 서식 지정 정보를 사용하여, 지정된 개체의 값을 32비트 부호 있는 정수로 변환합니다.

ToInt32(String, IFormatProvider)
지정된 문화권별 서식 지정 정보를 사용하여, 숫자의 지정된 문자열 표현을 해당하는 32비트 부호 있는 정수로 변환합니다.

ToInt32(String, Int32)
지정된 기수로 나타낸 숫자에 대한 문자열 표현을 32비트 부호 있는 정수로 변환합니다.

ToInt32(UInt64)
지정된 64비트 부호 없는 정수의 값을 해당하는 32비트 부호 있는 정수로 변환합니다.

ToInt32(Object)
지정된 개체의 값을 32비트 부호 있는 정수로 변환합니다.

ToInt32(SByte)
지정된 8비트 부호 있는 정수의 값을 해당하는 32비트 부호 있는 정수로 변환합니다.

ToInt32(Int64)
지정된 64비트 부호 있는 정수의 값을 해당하는 32비트 부호 있는 정수로 변환합니다.

ToInt32(Int32)
지정된 32비트 부호 있는 정수를 실제 변환 작업 없이 반환합니다.

ToInt32(Int16)
지정된 16비트 부호 있는 정수의 값을 해당하는 32비트 부호 있는 정수로 변환합니다.

ToInt32(Double)
지정된 배정밀도 부동 소수점 숫자 값을 해당하는 32비트 부호 있는 정수로 변환합니다.

ToInt32(Decimal)
지정된 10진수 값을 해당하는 32비트 부호 있는 정수로 변환합니다.

ToInt32(DateTime)
이 메서드를 호출하면 InvalidCastException이 항상 throw됩니다.

ToInt32(Char)
지정된 유니코드 문자의 값을 해당하는 32비트 부호 있는 정수로 변환합니다.

ToInt32(Byte)
지정된 8비트 부호 없는 정수의 값을 해당하는 32비트 부호 있는 정수로 변환합니다.

ToInt32(Boolean)
지정된 부울 값을 해당하는 32비트 부호 있는 정수로 변환합니다.
*/



string[] values = { "One", "1.34e28", "-26.87", "-18", "-6.00",
                    " 0", "137", "1601.9", Int32.MaxValue.ToString() };
int result;

foreach (string value in values)
{
   try {
      result = Convert.ToInt32(value);
      Console.WriteLine("Converted the {0} value '{1}' to the {2} value {3}.",
                        value.GetType().Name, value, result.GetType().Name, result);
   }
   catch (OverflowException) {
      Console.WriteLine("{0} is outside the range of the Int32 type.", value);
   }
   catch (FormatException) {
      Console.WriteLine("The {0} value '{1}' is not in a recognizable format.",
                        value.GetType().Name, value);
   }
}
// The example displays the following output:
//    The String value 'One' is not in a recognizable format.
//    The String value '1.34e28' is not in a recognizable format.
//    The String value '-26.87' is not in a recognizable format.
//    Converted the String value '-18' to the Int32 value -18.
//    The String value '-6.00' is not in a recognizable format.
//    Converted the String value ' 0' to the Int32 value 0.
//    Converted the String value '137' to the Int32 value 137.
//    The String value '1601.9' is not in a recognizable format.
//    Converted the String value '2147483647' to the Int32 value 2147483647.

/*특정 윈도우 Application에 Hook F5 Key 메세지 보내기*/

using NoName;
using NoName.Diagnostics;
using NoName.Text;//Encoding
using NoName.Runtime.InteropServices;

class HookingMessage
{
[DllImport("user32.dll", CharSet=CharSet.Auto)]
public static extern IntPtr SendMessage(IntPtr hWnd, int unMsg, IntPtr wParam, IntPtr lParam);

[DllImport("user32.dll", CharSet=CharSet.Auto)]
public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);

[DllImport("user32.dll")]
public static extern bool PostMessage(IntPtr hWnd, UInt32 Msg, int wParam, int lParam);

const UInt32 WM_KEYDOWN = 0x0100;
const int VK_F5 = 0x74;

public void running()
{
IntPtr ____handle_mmm=IntPtr.Zero;
bool ____toggle;

____handle_mmm = FindWindow(null, "CONSOLE.TRIS");
____toggle=PostMessage(____handle_mmm, WM_KEYDOWN, VK_F5, 0 );

if(____toggle==true) Console.WriteLine("PostMessage succ!!");
else Console.WriteLine("PostMessage fail!!");
}
}

class Program
{
public static void Main()
{
HookingMessage nm = new HookingMessage();
nm.running();
}
}



/*
namespace:System
Int To Double -> Convert.ToDouble(int or double)
Double to Int -> Convert.ToInt32(double)
*/

class TrisWidthHeight : Form
{
int titledepth, widthdepth, heightdepth;
public TrisWidthHeight()
{
titledepth = this.Height - this.ClientRectangle.Height;
titlewidth = Convert.ToInt32(Convert.ToDouble(titledepth / 10.0)) * 7
titleheight = Convert.ToInt32(Convert.ToDouble(titledepth / 10.0)) * 4
this.Width = titlewidth;
this.Height = titleheight;
}

 

Other Application기동을 클라이언트에서 하도록 수정(Other Application프로그램이 뛰워져 있지 않을경우에)
Other Application기동을 클라이언트에서 하도록 수정(Other Application프로그램이 뛰워져 있지 않을경우에)

____handle_mmm = FindWindow(null, "CONSOLE.TRIS");
if(____handle_mmm==IntPtr.Zero)
{
Console.WriteLine("Time:[" + DateTime.Now.ToString() + "]::" + "FindWindow(CONSOLE.TRIS) FAIL!!, Try Execute CONSOLE.TRIS Application!!");

Process process = Process.Start("____rcv.exe");

DateTime endTime = DateTime.Now.AddMinutes(1);

/*
System.Threading.Thread.Sleep(1000);
____handle_mmm = FindWindow(null, "CONSOLE.TRIS");
if(____handle_mmm==IntPtr.Zero) 
{
Console.WriteLine("Time:[" + DateTime.Now.ToString() + "]::" + "FindWindow(CONSOLE.TRIS) FAIL!!, Try Execute CONSOLE.TRIS Application!!");
}
*/

while(true)
{
if((____handle_mmm = FindWindow(null, "CONSOLE.TRIS"))==IntPtr.Zero)
{
System.Threading.Thread.Sleep(10);
}
else break;

if(endTime<DateTime.Now)
{
index=100;
break;
}
}
if(index==100) return;
}

 

 

____snd.cs
0.00MB





using NoName;
using NoName.Timers;

class Program
{
public static void Main()
{
ExampleManageCls nm = new ExampleManageCls();
nm.running();
}
}

class ExampleManageCls
{
Timer tm = new Timer();
DateTime endTime;

public void running()
{
tm.Elapsed += new ElapsedEventHandler(____time_tick);
tm.Interval = 1000;
tm.Start();

endTime = DateTime.Now.AddMinutes(1);

while(true)
{
if(endTime<DateTime.Now)
{
break;
}
}
}

void ____time_tick(object sender, ElapsedEventArgs e)
{
Console.WriteLine(DateTime.Now.ToString() + "/" + endTime.ToString());
}
}

/*RESULT-------------------------------------------------------
2022-03-28 오전 9:56:47/2022-03-28 오전 9:57:13
2022-03-28 오전 9:56:48/2022-03-28 오전 9:57:13
2022-03-28 오전 9:56:49/2022-03-28 오전 9:57:13
2022-03-28 오전 9:56:50/2022-03-28 오전 9:57:13
2022-03-28 오전 9:56:51/2022-03-28 오전 9:57:13
2022-03-28 오전 9:56:52/2022-03-28 오전 9:57:13
2022-03-28 오전 9:56:53/2022-03-28 오전 9:57:13
2022-03-28 오전 9:56:54/2022-03-28 오전 9:57:13
2022-03-28 오전 9:56:55/2022-03-28 오전 9:57:13
2022-03-28 오전 9:56:56/2022-03-28 오전 9:57:13
2022-03-28 오전 9:56:57/2022-03-28 오전 9:57:13
2022-03-28 오전 9:56:58/2022-03-28 오전 9:57:13
2022-03-28 오전 9:56:59/2022-03-28 오전 9:57:13
2022-03-28 오전 9:57:00/2022-03-28 오전 9:57:13
2022-03-28 오전 9:57:01/2022-03-28 오전 9:57:13
2022-03-28 오전 9:57:02/2022-03-28 오전 9:57:13
2022-03-28 오전 9:57:03/2022-03-28 오전 9:57:13
2022-03-28 오전 9:57:04/2022-03-28 오전 9:57:13
2022-03-28 오전 9:57:05/2022-03-28 오전 9:57:13
2022-03-28 오전 9:57:06/2022-03-28 오전 9:57:13
2022-03-28 오전 9:57:07/2022-03-28 오전 9:57:13
2022-03-28 오전 9:57:08/2022-03-28 오전 9:57:13
2022-03-28 오전 9:57:09/2022-03-28 오전 9:57:13
2022-03-28 오전 9:57:10/2022-03-28 오전 9:57:13
2022-03-28 오전 9:57:11/2022-03-28 오전 9:57:13
2022-03-28 오전 9:57:12/2022-03-28 오전 9:57:13
2022-03-28 오전 9:57:13/2022-03-28 오전 9:57:13

D:\tmp\console>
-------------------------------------------------------*/

/*2개의 Application이 동작한다. 2개의 Application이 Data를 Communication할때에 사용하는 방식이다.
1. Console에서 Key를 동작하여, 다른 Application으로 SendMessage(Text)한다. 일명 조정
2. 다른 Application에서는 WndProc(override frm)에서 WM_COPYDATA를 통해서 데이타를 받은다음에 
Key에 따라서 동작한다.
3. 억지로 말을 붙이자면, 한쪽방향으로의 클라이언트,서버의 관계이다.*/

>주의할점은 Tris Server Frm(No Key) 의 Application의 Handle이 반드시 일단 존재해야 한다.

____snd.cs
0.00MB

 

____rcv.cs
0.01MB

 

/*Data communication between Proesses!!*/

Windows OS
프로세스간 Window Handle 공유를 통한 SendMessage & WndProc(WM_COPYDATA)

참조)
SendMessage/FindWindow/Snd/Rcv Str :: 석수코딩교육 (tistory.com)

Linux & Unix OS
1) 프로세스간 Message Queue 공유를 통한 Message Send & Recv
2) 프로세스간 Semaphor & Shared Meory 공유를 통한 Message Send & Recv(비추)

/*
*상속안할경우 나오는 에러메세지*/


Microsoft (R) Visual C# Compiler version 4.8.4084.0
for C# 5
Copyright (C) Microsoft Corporation. All rights reserved.

This compiler is provided as part of the Microsoft (R) .NET Framework, but only supports language versions up to C# 5, which is no longer the latest version. For compilers that support newer versions of the C# programming language, see http://go.microsoft.com/fwlink/?LinkID=533240

ex12.cs(18,26): error CS0115: 'WindowsFrmManage.ProcessCmdKey(ref NoName.Windows.Forms.Message,
        NoName.Windows.Forms.Keys)': 재정의할 적절한 메서드를 찾을 수 없습니다.
ex12.cs(40,26): error CS0115: 'WindowsFrmManage.WndProc(ref NoName.Windows.Forms.Message)': 재정의할 적절한 메서드를 찾을 수 없습니다.

using NoName;
using NoName.Windows.Forms;

class Program
{
public static void Main(string[] args)
{
Application.Run(new WindowsFrmManage());
}
}
class WindowsFrmManage
{
public WindowsFrmManage() {}

protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
{
const int WM_KEYDOWN = 0x0100, WM_KEYUP = 0x0101, WM_CHAR = 0x0102, WM_SYSKEYDOWN = 0x0104, WM_SYSKEYUP = 0x0105, WM_PAINT = 0x000f, WM_SIZE = 0x0005;

if ((msg.Msg == WM_KEYDOWN) || (msg.Msg == WM_SYSKEYDOWN))
{
         switch (keyData.ToString())
{
case "Down"   :
break;
case "Escape" :
Application.Exit();
break;
         default:
             break;
         }
     }
return base.ProcessCmdKey(ref msg, keyData);
}

protected override void WndProc(ref Message m)//sdw_mh12e
{
const int WM_KEYDOWN = 0x0100, WM_KEYUP = 0x0101, WM_CHAR = 0x0102, WM_SYSKEYDOWN = 0x0104, WM_SYSKEYUP = 0x0105, WM_PAINT = 0x000f, WM_SIZE = 0x0005;

base.WndProc(ref m);

switch(m.Msg)
{
case WM_PAINT :
break;
default:
break;
}
}
}


using NoName;
using NoName.Windows.Forms;

class FrmIndex006 : Form
{
public FrmIndex006()
{
Console.WriteLine(">>>>FrmIndex006");
}
}

class FrmIndex007 : FrmIndex006
{
public FrmIndex007()
{
Console.WriteLine(">>>>FrmIndex007");
}
}

class FrmIndex008 : FrmIndex007
{
public FrmIndex008()
{
Console.WriteLine(">>>>FrmIndex008");
}
}

class FrmIndex009 : FrmIndex008
{
public FrmIndex009()
{
Console.WriteLine(">>>>FrmIndex009");
}
}

class FrmIndex010 : FrmIndex009
{
public FrmIndex010()
{
Console.WriteLine(">>>>FrmIndex010");
}
}

class FrmMain : FrmIndex010
{
public FrmMain()
{
Console.WriteLine(">>>>FrmMain");
}
protected override void WndProc(ref Message m)
{
const int WM_KEYDOWN = 0x0100, WM_SYSKEYDOWN = 0x0104, WM_PAINT = 0x000f, WM_SIZE = 0x0005;

base.WndProc(ref m);

try
{
switch(m.Msg)
{
case WM_PAINT :
DialogResult dialogResult = MessageBox.Show(">>Quit OK!!", "Inform",
              MessageBoxButtons.OKCancel, MessageBoxIcon.Information);

if (dialogResult == DialogResult.OK) Application.Exit();
break;
default:
break;
}
}
catch(Exception ex)
{
Console.WriteLine(ex.Message);
}
}
}
/*
D:\tmp\console>sample
>>>>FrmIndex006
>>>>FrmIndex007
>>>>FrmIndex008
>>>>FrmIndex009
>>>>FrmIndex010
>>>>FrmMain

D:\tmp\console>
*/

class Program
{
public static void Main()
{
Application.Run(new FrmMain());
}
}


Server : Redis Server

1. Language : c,pro*c,socket,oracle

Client : Redis Client

1. Language : c#
2. IDE : visual studio 2019 professional
3. Core
    3.1 BackgroundWorker
    3.2 WndProc - WM_COPYDATA
    3.3 SendMessage
    3.4 DLL

다형성(polymorphism)은 무엇인가요?

polymorphism에서 poly는 여러, 다양한(many), morph는 변형(change)이나 형태(form)의 의미를 가지고 있습니다. 
사전적 정의로만 살펴보면 "여러가지 형태"를 나타내는데, 이를 객체 지향 프로그래밍으로 끌고 온다면 "하나의 객체가 여러 개의 형태를 가질 수 있는 능력"이라 말할 수 있습니다. 


우리는 이미 다형성을 접해본 적이 있습니다. 다형성의 일부인 메소드의 오버로딩(이는 ad-hoc polymorphism에 해당)과 오버라이딩(이는 inclusion polymorphism에 해당)에서 말이죠! 
C#도 객체 지향 프로그래밍에 근간을 두고 있으므로 이 다형성이라는 개념은 자주 사용됩니다.

클래스의 상속(Class inheritance)

상속이란 말을 어디선가 들어본 적이 있는 것 같지 않나요? 
짐작하는 그 상속이 맞냐구요? 네 맞습니다. 
혹시나 상속이 뭔지 들어보 적 없는 분들을 위해 무엇인지 알려드리려고 합니다. 
상속이란 네이버 지식백과를 빌어 다음과 같이 정의되어 있습니다. 
'일정한 친족적 관계가 있는 사람 사이에 한 쪽이 사망하거나 법률상의 원인이 발생하였을 때 재산적 또는 친족적 권리와 의무를 계승하는 제도'. 
즉, 부모님이 돌아가셨다고 할 때 그 유산을 자식이 물려받는 것이라고 할 수 있습니다. 
클래스의 상속도 이와 똑같습니다. 
객체 지향 프로그래밍에선 부모 클래스와 자식 클래스가 있는데, 
부모 클래스는 자식 클래스의 기반이 된다 하여 기반 클래스라고 부르기도 하고, 
자식 클래스는 부모 클래스로부터 파생되었다고 해서 파생 클래스라고도 부르기도 합니다.

C#에서, 클래스를 다른 클래스로 상속하려면 다음과 같이 클래스 이름 뒤에 콜론(:)을 추가하고 상속하려는 클래스의 이름을 덧붙이시면 됩니다.

using NoName;
using NoName.Windows.Forms;
using NoName.Timers;

class FrmMain : Form
{
NoName.Timers.Timer tm = new NoName.Timers.Timer();
FrmChild f1 = new FrmChild();

int ____width=0;
int ____height=0;
int ____idx=0;

public FrmMain()
{
this.Text="FrmMain";

tm.Elapsed += new ElapsedEventHandler(____time_tick);
tm.Interval = 1000;
tm.Start();

f1.Show();
}
void ____time_tick(object sender, ElapsedEventArgs e)
{
this.Width = f1.Width + ____width;
this.Height = f1.Height + ____height;

____width += 10;
____height += 10;

____idx++;
if(____idx==13) f1.Close();
if(____idx==14) this.Close();

this.Text = "FrmMain" + ">>>[" + ____idx.ToString("0000") + "]";
}
protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
{
const int WM_KEYDOWN = 0x0100, WM_SYSKEYDOWN = 0x0104, WM_PAINT = 0x000f, WM_SIZE = 0x0005;

if ((msg.Msg == WM_KEYDOWN) || (msg.Msg == WM_SYSKEYDOWN))
{
         switch (keyData.ToString())
         {
case "Return" :
DialogResult dialogResult = MessageBox.Show("[" + this.Text + "]" + ">>Quit OK!!", "Inform",
              MessageBoxButtons.OKCancel, MessageBoxIcon.Information);

if (dialogResult == DialogResult.OK) Application.Exit();
break;
case "Right"  :
break;
case "Left"   :
break;
         default:
             break;
         }
     }
return base.ProcessCmdKey(ref msg, keyData);
}
protected override void WndProc(ref Message m)
{
const int WM_KEYDOWN = 0x0100, WM_SYSKEYDOWN = 0x0104, WM_PAINT = 0x000f, WM_SIZE = 0x0005;

base.WndProc(ref m);

try
{
switch(m.Msg)
{
case WM_PAINT :
break;
default:
break;
}
}
catch(Exception ex)
{
Console.WriteLine(ex.Message);
}
}
}

class FrmChildBase : Form
{
//
}

class FrmChild : FrmChildBase
{
public FrmChild()
{
this.Width=400;
this.Height=400;

this.Text="FrmChild";
}
}

class Program
{
public static void Main()
{
Application.Run(new FrmMain());
}
}






+ Recent posts