728x90

클래스의 멤버 변수를 private, public 으로 선언할 것인가에 따라 정보은닉, 정보공개를 고민하게 된다.

private 로 선언하면 getter 메소드, setter 메소드를 구현해야 한다.


C# 언어에서는 다양한 이유로 프로퍼티의 사용을 장려한다. 지금까지도 타입(type)에서 public 데이터 변수를 사용하거나, get/set류의 메서드를 직접 만들어서 사용하고 있다면 이제 그런 방법을 사용하지 않는 것이 좋다. 프로퍼티는 우리가 만든 타입의 값을 외부에서 접근할 수 있도록 하면서 동시에 객체지향에서 논의되는 캡슐화를 지원한다. 프로퍼티는 데이터 멤버처럼 접 근가능하면서 메서드의 형태로 구현되는 C# 언어의 요소이다.


프로퍼티(속성)를 사용하면 클래스가 구현 또는 코드를 숨기는 동시에 값을 가져오고 설정하는 방법을 공개적으로 노출할 수 있다.
- get 속성 접근자는 속성 값을 반환하고, set 접근자는 새 값을 할당하는데 사용한다.
- set 접근자의 value 키워드는 set 접근자가 할당하는 값을 정의하는데 사용한다.
- set 접근자만을 구현하면 쓰기 전용, get 접근자만을 구현하면 읽기 전용이다.
- value : set 접근자 사용 시 사용되는 암묵적 매개변수


자동구현 프로퍼티

using System;

namespace Property
{
    class Test
    {
        private int x;
        public int X   // 프로퍼티
        {
            get { return x; }
            set {
                x = value; // value : set 접근자 사용시 사용되는 암묵적 매개변수
            }
        }
    }

    class Person
    {
        public string Name { get; set; } // 자동 구현 프로퍼티
        public int Age { get; } // 읽기전용, 자동 구현 프로퍼티
        public int grade { get; } = 5; // 자동속성초기화
        public Person(string name, int age) // 생성자
        {
            this.Name = name;
            this.Age = age;
        }
        
        public override string ToString()
        {
            return $"name={Name}, age={this.Age}, grade={grade}";
        }
    }


    public class SaleItem
    {
        public string Name // 자동 구현 프로퍼티
        { get; set; }

        public decimal Price // 자동 구현 프로퍼티
        { get; set; }
    }

    class Program
    {
        static void Main(string[] args)
        {
            Test t1 = new Test();
            t1.X = 5000;              // 프로퍼티 set 접근자를 통한 값 지정
            Console.WriteLine(t1.X);  // 프로퍼티 get 접근자를 통한 출력

            Person a = new Person("Tom", 14);
            Console.WriteLine(a);

            var item = new SaleItem { Name = "구두", Price = 150000 };
            Console.WriteLine($"{item.Name}의 판매 가격은 {item.Price}");
        }
    }
}


Program.cs


'C# > 문법 및 기능' 카테고리의 다른 글

C# 인터페이스  (0) 2019.08.18
C# 구조체(Struct)  (0) 2019.08.14
C# 접근 제한자(Access Modifier)  (0) 2019.08.13
자바와 C#의 차이점  (0) 2016.12.27
C# NameValueCollection  (0) 2016.03.20
블로그 이미지

Link2Me

,
728x90

C# 인터페이스

- 인터페이스는 메서드, 속성(Property), 이벤트, 인덱서만을 가질 수 있으며, 이를 직접 구현하지 않는다.

- 인터페이스는 필드를 포함할 수 없다.

- 정의부분만 표현하고, 구현 부분은 상속받은 클래스에서 구현한다. (구현이라 함은 {}가 포함된 거)
- 인터페이스는 추상 멤버(abstract member)로만 구성된 추상 Base 클래스(abstract base class)와 개념적으로 유사하다.
- 클래스가 인터페이스를 가지는 경우 해당 인터페이스의 모든 멤버에 대한 구현(implementation)을 제공해야 한다.
- C# 클래스가 인터페이스를 갖는 경우 인터페이스의 모든 멤버에 대한 구현을 제공해야 한다.

- 여러개의 인터페이스를 부모로 둘 수 있다. (다중 상속 가능)
- 인터페이스로 객체를 생성할 수는 없다.

참고사항
public class Staff : IEmployee
를 보면 C#은 상속이 Class 인지, Interface 인지 구별없이 사용한다.
Java 는 Class 상속은 extends, Interface 구현은 implements 로 구별하고 있다.
그래서 C#에서는 인터페이스라는 걸 구별하기 위해 암묵적으로 대문자 I를 붙여주는 거 같다.

public class Staff : IEmployee

출처: https://link2me.tistory.com/1671 [소소한 일상 및 업무TIP 다루기]


예제 1

using System;

namespace Interface_01
{
    interface IEmployee
    {
        // 멤버 앞에 접근제한자 사용 안함
        string getName();
        void setName(string n);
        int getCounter();
    }

    public class Staff : IEmployee
    {
        // IEmployee 구현, 인터페이스라는 걸 구분하기 위해서 앞에 대문자 I를 붙인다.
        private String name;
        private int counter;
        public static int NOofEmployees;

        public string getName()
        {
            return name;
        }

        public void setName(string name)
        {
            this.name = name;
        }

        public int getCounter()
        {
            return counter;
        }

        public Staff() // 생성자
        {
            counter = ++counter + NOofEmployees;
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            string name;
            Console.Write("직원 수 입력: ");
            Staff.NOofEmployees = int.Parse(Console.ReadLine());

            Staff my = new Staff();
            Console.Write("신입 직원의 이름을 입력하세요: ");
            name = Console.ReadLine();
            my.setName(name);

            Console.WriteLine("▷ 직원 정보 ◁");
            Console.WriteLine("직원 번호 : {0}, 직원이름 : {1} : ", my.getCounter(),my.getName());
          
        }
    }
}


예제2 : 프로퍼티 속성을 이용한 인터페이스 구현

using System;

namespace Interface_02
{
    interface IEmployee
    {
        // 멤버 앞에 접근제한자 사용 안함
        string Name { get;set; } // 읽기, 쓰기 모두 가능한 프로퍼티
        int Counter { get; }  // 읽기 전용 프로퍼티
    }

    public class Staff : IEmployee
    {
        // IEmployee 구현, 인터페이스라는 걸 구분하기 위해서 앞에 대문자 I를 붙인다.
        private String name;
        private int counter;
        public static int NOofEmployees; // static 키워드를 사용해서 객체 생성없이 필드 사용

        public string Name  // 읽기, 쓰기 모두 가능한 프로퍼티
        {
            get { return name; }
            set { name = value; }
        }

        public int Counter  // 읽기 전용 프로퍼티
        {
            get { return counter; }
        }

        public Staff() // 생성자
        {
            counter = ++counter + NOofEmployees;
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            string name;
            Console.Write("직원 수 입력: ");
            Staff.NOofEmployees = int.Parse(Console.ReadLine());

            Staff my = new Staff();
            Console.Write("신입 직원의 이름을 입력하세요: ");
            name = Console.ReadLine();
            my.Name = name;

            Console.WriteLine("▷ 직원 정보 ◁");
            Console.WriteLine("직원 번호 : {0}, 직원이름 : {1} : ", my.Counter, my.Name);

        }
    }
}



Base()
this는 각각의 메모리를 구분하기위한 방법이며, 생성자를 호출하기 위한 방법으로 사용된다.
이외에 부모와 자식간의 메모리를 구분하기 위한 키워드가 바로 base키워드이다.
부모 클래스의 이름으로는 부모 클래스의 생성자를 호출할 수 없고 base 키워드를 사용해야 한다.

    public class Parent
    {
        private int i;

        public Parent(int i)
        {
            this.i = i;
        }
    }

    public class Child : Parent
    {
        private int j;

        public Child(int i, int j) : base(i)    // 부모 클래스의 생성자를 호출하려면 base 키워드를 사용해야 한다.
        {
            this.j = j;
        }
    }
 


Program.cs


'C# > 문법 및 기능' 카테고리의 다른 글

C# 프로퍼티(Property)  (0) 2019.08.19
C# 구조체(Struct)  (0) 2019.08.14
C# 접근 제한자(Access Modifier)  (0) 2019.08.13
자바와 C#의 차이점  (0) 2016.12.27
C# NameValueCollection  (0) 2016.03.20
블로그 이미지

Link2Me

,
728x90

구조체는 사용자 정의 Data Type 으로 int, double 등과 같은 기본 제공 변수 유형이 아닌
새로운 유형, 여러가지 유형을 사용하기 위해 사용자가 직접 만들어 사용한다.
- 구조체를 정의하려면 struct 문을 사용한다.
- C# 구조체에 메소드, 필드, 속성등을 가질 수 있다.
- C# 구조체에 기본(Default) 생성자를 정의할 수 없다.
- C# 구조체에 소멸자를 정의할 수 없다.
- 클래스는 힙에 생성되는 참조 유형이고 구조체는 스택에 생성되는 값 유형이다.
- 구조체는 상속을 지원하지 않는다.

- 클래스와 달리 구조체는 new 연산자를 사용하지 않고 인스턴스화할 수 있다.


using System;

namespace Struct_EX
{
    class BaseClass // 부모 클래스
    {
        public int a; // 클래스의 멤버를 접근 제한자로 지정하지 않으면 멤버의 접근 수준은 무조건 private로 자동 지정됨
        int b;

        private void A() { }
        protected void B() { }

        public void C() { }

        public void ParentMethod() // 부모클래스의 ParentMethod 메소드
        {
            A();
            B();
            C();
        }
    }
    class DerivedClass : BaseClass // DerivedClass (파생) 클래스는 BaseClass(부모클래스)를 상속받는다
    {
        public void ChildMethod()
        {
            //A(); // private 접근 지시어로 선언된 메소드 접근은 같은 클래스 안에서만 접근 가능
            B(); // protected 접근 지시어로 선언되었고 자식 클래스는 부모 클래스의 파생 클래스 이므로 접근 가능
            C();
        }

    }

    class Program
    {
        struct MyPoint // 클래스와 유사한 구문, 상속 불가, 인터페이스 구현 불가
        {
            public int x;
            public int y;

            public MyPoint(int x, int y) // 구조체의 생성자는 매개변수를 넣어 만들어야 한다.
            {
                this.x = x;
                this.y = y;
            }

            public override string ToString()
            {
                return string.Format("({0}, {1})", x, y);
            }
        }

        class PointC
        {
            public int x;
            public int y;
            public PointC(int x, int y)
            {
                this.x = x;
                this.y = y;
            }
        }

        static void Main(string[] args)
        {
            BaseClass parent = new BaseClass(); // Baseclass(부모) 클래스로 새 객체를 생성한다.
            parent.a = 1; // 보호수준 때문에 접근 불가
            DerivedClass child = new DerivedClass(); // DerivedClass(자식) 클래스로 새 객체를 생성한다.
            parent.ParentMethod();
            child.ChildMethod();
            child.C();

            MyPoint p; // 클래스와 달리 구조체는 new 연산자를 사용하지 않고 인스턴스화할 수 있다.
            p.x = 55;
            p.y = 77;
            Console.WriteLine("구조체 : p.x = {0}, p.y = {1}", p.x, p.y);
            Console.WriteLine(p.ToString());

            MyPoint p1 = new MyPoint(11,22); //구조체 선언
            PointC p2 = new PointC(11,22);  //클래스 선언
            MyPoint p3 = p1; // 값에 의한 복사 (구조체는 스택에 생성되는 값 타입)
            PointC p4 = p2; // 참조에 의한 복사 (클래스는 힙에 생성되는 참조 타입으로 힙의 주소를 전달)
            Console.WriteLine("구조체 : p1.x = {0}, p1.y = {1}", p1.x, p1.y);
            Console.WriteLine("클래스 : p2.x = {0}, p2.y = {1}", p2.x, p2.y);

            p3.x = 33;
            p4.x = 44;
            Console.WriteLine("구조체 : 값에 의한 복사 p1.x = {0}, p3.x = {1}", p1.x, p3.x);

            // 구조체는 스택영역에 값이 직접 들어가서 깊은 복사가 된다.

            Console.WriteLine("클래스 : 참조에 의한 복사 p2.x = {0}, p4.x = {1}", p2.x, p4.x);
            // 클래스는 참조하는 주소가 복사되면서 스택영역의 변수가 같은 힙영역을 가리킨다.
        }
    }
}



'C# > 문법 및 기능' 카테고리의 다른 글

C# 프로퍼티(Property)  (0) 2019.08.19
C# 인터페이스  (0) 2019.08.18
C# 접근 제한자(Access Modifier)  (0) 2019.08.13
자바와 C#의 차이점  (0) 2016.12.27
C# NameValueCollection  (0) 2016.03.20
블로그 이미지

Link2Me

,
728x90

접근 제한자(Access Modifier) : 외부로부터 타입(class, struct, inteface, delegate )나 위 타입들의 멤버들(method, property, event, field)로의 접근을 제한할 때 사용한다.


클래스 멤버는 5가지의 접근 제한자를 (public, internal, private, protected, protected internal) 모두 가질 수 있지만, 구조체(struct) 멤버는 상속이 되지 않으므로 3가지의 접근 제한자만 (public, internal, private) 가질 수 있다.


접근 제한자

클래스 내부

외부 클래스

파생(자식) 클래스

프로젝트

 public





 protected


 


 

 internal



 

 private

 

 

 

 protected internal


 

 


어셈블리는 하나의 단일한 단위로 존재하는 .NET의 실행 가능한 프로그램 또는 실행 프로그램의 일부이며  실행 및 배포의 단위라고 할 수 있다. C# 응용 프로그램 작성의 결과로 생긴 .exe 파일, 클래스 라이브러리 작성의 결과인 DLL이 각각 하나의 어셈블리 이다.
하나의 단일한 어셈블리 안의 모든 코드는 하나의 단일한 단위로 빌드, 배포되며 버전 번호가 부여되는데 각 어셈블리는 다른 프로그램들이 사용 할 수 있는 pulic class, 속성, 메소드 등을 노출하고, private으로 선언된 것들은 모두 어셈블리 안에 은폐된다.


internal
동일한 어셈블리 내에 있는 다른 타입들이 접근할 수 있다.


protected
파생 클래스에서 이 클래스 멤버에 접근할 수 있다.

private
클래스 내부와 구조체 내에서만 멤버에 접근 가능하다.


using System;

namespace ClassModifier
{
    class BaseClass // 부모 클래스
    {
        int a; // 클래스의 멤버를 접근 제한자로 지정하지 않으면 멤버의 접근 수준은 무조건 private로 자동 지정됨
        int b;

        private void A() { }
        protected void B() { }

        public void C() { }

        public void ParentMethod() // 부모클래스의 ParentMethod 메소드
        {
            A();
            B();
            C();
        }
    }
    class DerivedClass : BaseClass // DerivedClass (파생) 클래스는 BaseClass(부모클래스)를 상속받는다
    {
        public void ChildMethod()
        {
            //A(); // private 접근 지시어로 선언된 메소드 접근은 같은 클래스 안에서만 접근 가능
            B(); // protected 접근 지시어로 선언되었고 자식 클래스는 부모 클래스의 파생 클래스 이므로 접근 가능
            C();
        }

    }

    class Program
    {
        static void Main(string[] args)
        {
            BaseClass parent = new BaseClass(); // Baseclass(부모) 클래스로 새 객체를 생성한다.
            parent.a = 1; // 보호수준 때문에 접근 불가
            DerivedClass child = new DerivedClass(); // DerivedClass(자식) 클래스로 새 객체를 생성한다.
            parent.ParentMethod();
            child.ChildMethod();
            child.C();
        }
    }
}



'C# > 문법 및 기능' 카테고리의 다른 글

C# 인터페이스  (0) 2019.08.18
C# 구조체(Struct)  (0) 2019.08.14
자바와 C#의 차이점  (0) 2016.12.27
C# NameValueCollection  (0) 2016.03.20
C# Dictionary 와 comboBox 연결  (0) 2016.02.08
블로그 이미지

Link2Me

,
728x90

Java 와 C#이 어떻게 다른지 설명이 잘된 글이 있어서 가져왔다.


출처 : http://www.elex.pe.kr/entry/Java-cf-C-Sharp

프로그램 구조

Java

package hello;


public class HelloWorld {
   public static void main(String[] args) {
      String name = "Java";

      // 매개변수를 확인
      if (args.length == 1)
         name = args[0];

      System.out.println("Hello, " + name + "!");
    }
}

C#

using System; 

namespace Hello {
   public class HelloWorld {
      public static void Main(string[] args) {
         string name = "C#";

         // 매개변수를 확인
         if (args.Length == 1)
            name = args[0];

         Console.WriteLine("Hello, " + name + "!");
      }
   }
}

Java 소스 파일의 확장자는 *.java이고, C#은 *.cs이다.

Java는 클래스마다 별도의 파일을 작성해야 하고 클래스명과 파일명이 일치해야 하지만, C#에서는 하나 이상의 최상위 클래스를 작성할 수 있고 파일명에 대한 제한도 없다.

Java

package harding.compsci.graphics;










// 단일 클래스를 임포트
import harding.compsci.graphics.Rectangle;
// 여러 클래스를 임포트
import harding.compsci.graphics.*; 

C#

namespace Harding.Compsci.Graphics {
  ...
}
또는
namespace Harding {
  namespace Compsci {
    namespace Graphics {
      ...
    }
  }
}
// 단일 클래스를 임포트
using Rectangle = Harding.CompSci.Graphics.Rectangle;
// 여러 클래스를 임포트
using Harding.Compsci.Graphics;

Java는 소스 코드의 첫 줄에 package를 선언하지만, C#에서는 namespace 키워드를 사용해서 블록으로 묶는다. C#에서는 하나의 소스 코드 파일에 여러 개의 네임스페이스를 포함시는 것도 가능하다.

Java의 import 키워드 대신, C#에서는 using 키워드를 사용한다. using 키워드를 namespace 블록 내부에 사용할 수도 있다. using 키워드를 사용해서 별칭을 지정할 수도 있다.

주석

Java

// 한 줄 주석
/* 여러 줄
    주석  */
/** 자바독 문서화 주석 */

C#

// 한 줄 주석
/* 여러 줄
    주석  */
/// 한 줄 XML 주석
/** 여러 줄 XML 주석 */

자료형

Java

원시 자료형
boolean
byte
char
short, int, long
float, double


참조 자료형
Object   (다른 모든 클래스들의 부모 클래스)
String
arrays, classes, interfaces

형 변환
// 정수를 문자열로 
int x = 123; 
String y = Integer.toString(x);  // y is "123"
// 문자열을 정수로
y = "456"; 
x = Integer.parseInt(y);   // x is 456
// 부동소수를 정수로
double z = 3.5; 
x = (int) z;   // x는 3  (소수부는 잘림)

C#

값 타입
bool
byte, sbyte
char
short, ushort, int, uint, long, ulong
float, double, decimal
structures, enumerations

참조 자료형
object    ( 다른 모든 클래스들의 부모 클래스)
string
arrays, classes, interfaces, delegates

형 변환
// 정수를 문자열로 
int x = 123; 
String y = x.ToString();  // y is "123"
// 문자열을 정수로
y = "456"; 
x = int.Parse(y);   // 또는 x = Convert.ToInt32(y);
// 부동소수를 정수로
double z = 3.5; 
x = (int) z;   // x는 3  (소수부는 잘림)

Java에서 지원되는 원시 자료형과 더불어, C#에서는 부호 없는(unsigned) 자료형과 128비트 부동 소수 형식(decimal)을 추가로 지원한다.

Java에서는 원시 자료형이 존재하고 각각의 래퍼 클래스가 존재하지만, C#에서 모든 원시 자료형은 System 네임스페이스의 객체이며 각각 별칭이 존재한다.

Java의 boolean은 C#에서 bool이다.

상수

Java

// 생성자에서 초기화 될 수 있음
final double PI = 3.14;

C#

const double PI = 3.14;

// const 또는 변수에 지정할 수 있음. 생성자에서 초기화 될 수 있음.
readonly int MAX_HEIGHT = 9;

Java에서는 final 키워드를, C#에서는 const와 readonly 키워드를 사용한다.

const 키워드를 사용하면 런타임시에 값을 변경할 수 없지만, readonly 키워드를 지정하면 런타임시에 단 한번 값을 지정할 수 있다.

열거형

Java

enum Action {Start, Stop, Rewind, Forward};
// 특수한 형태의 클래스이다. 
enum Status {
  Flunk(50), Pass(70), Excel(90);
  private final int value;
  Status(int value) { this.value = value; }
  public int value() { return value; } 
};
Action a = Action.Stop;
if (a != Action.Start)
  System.out.println(a);      // Prints "Stop"
Status s = Status.Pass;
System.out.println(s.value());      // Prints "70"

C#

enum Action {Start, Stop, Rewind, Forward};
enum Status {Flunk = 50, Pass = 70, Excel = 90};






Action a = Action.Stop;
if (a != Action.Start)
  Console.WriteLine(a);             // Prints "Stop"
Status s = Status.Pass;
Console.WriteLine((int) s);       // Prints "70"

Java 1.5 이상에서 enum을 지원한다.

C# 3.0 이상에서는 확장메서드를 통해서 enum 타입에 메서드를 정의할 수 있다.

연산자

Java

비교
==  <  >  <=  >=  !=

산술
+  -  *  /
%  (mod)
/   (integer division if both operands are ints)
Math.Pow(x, y)

할당
=  +=  -=  *=  /=   %=   &=  |=  ^=  <<=  >>=  
>>>= ++ -- 비트 & | ^ ~ << >> >>> 논리 && || & | ^ ! 문자열 결합 +

C#

비교
==  <  >  <=  >=  !=

산술
+  -  *  /
%  (mod)
/   (integer division if both operands are ints)
Math.Pow(x, y)

할당
=  +=  -=  *=  /=   %=  &=  |=  ^=  <<=  >>=  ++  --


비트
&  |  ^   ~  <<  >>

논리
&&  ||  &  |   ^   !

문자열 결합
+

연산자 오버로딩
public static ComplexNumber operator+(ComplexNumber a, ComplexNumber b) { ...

Java의 >>> 연산자는 C#에서 사용할 수 없다. 이는 부호없는 자료형이 지원되기 때문이다.

C#의 checked, unchecked 키워드를 사용해서 오버플로우를 검사할 수 있다.

C#에서는 연산자 오버로딩을 위해 operator 키워드를 지원한다.

연산자 오버로딩은 static 메서드로 선언하고 메서드 이름 대신에 operator 키워드와 연산자 심볼을 붙인다.

조건문

Java

greeting = age < 20 ? "What's up?" : "Hello";

if (x < y) 
  System.out.println("greater");

if (x != 100) {    
  x *= 5; 
  y *= 2; 
} 
else 
  z *= 6;

int selection = 2;
switch (selection) { // byte, short, int, char, enum
  case 1: x++;   // break가 없으면 다음으로 넘어간다
  case 2: y++;   break; 
  case 3: z++;   break; 
  default: other++;
}

C#

greeting = age < 20 ? "What's up?" : "Hello";

if (x < y)  
  Console.WriteLine("greater");

if (x != 100) {    
  x *= 5; 
  y *= 2; 
} 
else 
  z *= 6;

string color = "red";
switch (color) {    //자료형 제한이 없다.
  case "red":    r++;    break;  // break 꼭 필요
  case "blue":   b++;   break; 
  case "green": g++;   break; 
  default: other++;     break; 
}

Java 7이후부터 switch문에 문자열을 사용할 수 있다.

Java와 달리 C#에서는 case문 다음에 반드시 break문이 존재해야 한다.

반복문

Java

while (i < 10) 
  i++;

for (i = 2; i <= 10; i += 2) 
  System.out.println(i);

do 
  i++; 
while (i < 10);

for (int i : numArray)  // foreach construct  
  sum += i;

import java.util.ArrayList;
ArrayList<Object> list = new ArrayList<Object>();
list.add(10); 
list.add("Bisons");
list.add(2.3);    
for (Object o : list)
  System.out.println(o);

C#

while (i < 10) 
  i++;

for (i = 2; i <= 10; i += 2) 
  Console.WriteLine(i);

do 
  i++; 
while (i < 10);

foreach (int i in numArray)  
  sum += i;
 
using System.Collections;
ArrayList list = new ArrayList();
list.Add(10);
list.Add("Bisons");
list.Add(2.3);
foreach (Object o in list)
  Console.WriteLine(o);

배열

Java

int nums[] = {1, 2, 3};   
     또는   int[] nums = {1, 2, 3};

for (int i = 0; i < nums.length; i++)
  System.out.println(nums[i]);

String names[] = new String[5];
names[0] = "David";

float twoD[][] = new float[rows][cols];
twoD[2][0] = 4.5;

int[][] jagged = new int[5][]; 
jagged[0] = new int[5]; 
jagged[1] = new int[2]; 
jagged[2] = new int[3]; 
jagged[0][4] = 5;

C#

int[] nums = {1, 2, 3};


for (int i = 0; i < nums.Length; i++)
  Console.WriteLine(nums[i]);

string[] names = new string[5];
names[0] = "David";

float[,] twoD = new float[rows, cols];
twoD[2,0] = 4.5f;

int[][] jagged = new int[3][] {
    new int[5], new int[2], new int[3] }; 
jagged[0][4] = 5;

Java와 달리 C#에서는 배열을 나타내는 대괄호 []는 반드시 자료형 다음에 와야 한다.

배열의 초기화 시에도, Java와 달리 C#에서는 배열의 크기와 초기값의 수가 일치해야 한다.

C#에서는 Jagged 배열 외에 다차원 배열을 추가로 지원한다.

메서드

Java

// 값을 반환
int Add(int x, int y) { 
   return x + y; 
}

int sum = Add(2, 3);
// 결과값을 반환하지 않음
void PrintSum(int x, int y) { 
   System.out.println(x + y); 
}
PrintSum(2, 3); 

// 값에 의한 전달
void TestFunc(int x, Point p) {
   x++; 
   p.x++;       // 객체 값 변경
   p = null;    // 객체 참조를 제거 
}
class Point { 
   public int x, y; 
}
Point p = new Point(); 
p.x = 2; 
int a = 1; 
TestFunc(a, p);
System.out.println(a + " " + p.x + " " + (p == null) );  
// 1 3 false // 임의의 갯수의 매개변수 int Sum(int ... nums) { int sum = 0; for (int i : nums) sum += i; return sum; } int total = Sum(4, 3, 2, 1); // returns 10

C#

// 값을 반환
int Add(int x, int y) { 
   return x + y; 
}

int sum = Add(2, 3);
// 결과값을 반환하지 않음
void PrintSum(int x, int y) { 
   Console.WriteLine(x + y); 
}
PrintSum(2, 3); 

// 값에 의한 전달, ref, out
void TestFunc(int x, ref int y, out int z, Point p1, ref Point p2) { 
   x++;  y++;  z = 5; 
   p1.x++;       // 객체 값 변경     
   p1 = null;    // 객체 참조를 제거 
   p2 = null;   // 객체 참조를 제거 
}
class Point { 
   public int x, y; 
}
Point p1 = new Point(); 
Point p2 = new Point(); 
p1.x = 2; 
int a = 1, b = 1, c;   // out은 초기화 필요 없음
TestFunc(a, ref b, out c, p1, ref p2); 
Console.WriteLine("{0} {1} {2} {3} {4}", 
   a, b, c, p1.x, p2 == null);   // 1 2 5 3 True

// 임의의 갯수의 매개변수
int Sum(params int[] nums) {
  int sum = 0;
  foreach (int i in nums)
    sum += i;
  return sum;
}
int total = Sum(4, 3, 2, 1);   // returns 10

C#에서는 값 형식의 데이터를 참조 형식으로 매개변수를 전달하기 위해서 ref, out 키워드를 지원한다.

ref의 경우 사용하기 전에 반드시 초기화 되어 있어야 하고, out의 경우 메서드 내에서 사용하기 전에 값을 할당해야 한다.

임의의 갯수의 매개변수를 전달 받으려는 경우, Java는 ...을, C#은 params 키워드를 사용한다.

문자열

Java

// 결합
String school = "Harding "; 
school = school + "University";   // school is "Harding University"

// 비교
String mascot = "Bisons"; 
if (mascot == "Bisons")    // 틀려!
if (mascot.equals("Bisons"))   // true
if (mascot.equalsIgnoreCase("BISONS"))   // true
if (mascot.compareTo("Bisons") == 0)   // true
System.out.println(mascot.substring(2, 5));   // Prints "son"

// 날짜
java.util.Calendar c 
  = new java.util.GregorianCalendar(1973, 10, 12);
String s 
  = String.format("My birthday: %1$tb %1$te, %1$tY", c);

// 조작가능한 문자열 
StringBuffer buffer = new StringBuffer("two "); 
buffer.append("three "); 
buffer.insert(0, "one "); 
buffer.replace(4, 7, "TWO"); 
System.out.println(buffer);     // Prints "one TWO three"

String path = "\\\\FileShare\\Directory\\file.txt";

C#

// 결합
string school = "Harding "; 
school = school + "University";   // school is "Harding University"

// 비교
string mascot = "Bisons"; 
if (mascot == "Bisons")    // true
if (mascot.Equals("Bisons"))   // true
if (mascot.ToUpper().Equals("BISONS"))   // true
if (mascot.CompareTo("Bisons") == 0)    // true
Console.WriteLine(mascot.Substring(2, 3));    // Prints "son"

// 날짜
DateTime dt 
  = new DateTime(1973, 10, 12);
string s 
  = "My birthday: " + dt.ToString("MMM dd, yyyy");

// 조작가능한 문자열 
System.Text.StringBuilder buffer = 
new System.Text.StringBuilder("two "); buffer.Append("three "); buffer.Insert(0, "one "); buffer.Replace("two", "TWO"); Console.WriteLine(buffer); // Prints "one TWO three" string path = @"\\FileShare\Directory\file.txt";

문자열 비교시에, Java는 equals() 메서드를 사용하지만, C#에서는 == 또는 != 연산자를 사용할 수 있다.

C#에서는 변수에 할당되는 문자열 앞에 @을 붙여서 이스케잎 문자를 효율적으로 처리할 수 있다.

예외처리

Java

// 메서드에서 예외를 던질 수 있도록 선언되어야 함
Exception ex 
  = new Exception("Something is really wrong."); 
throw ex;  

try {
  y = 0; 
  x = 10 / y;
} catch (Exception ex) {
  System.out.println(ex.getMessage()); 
} finally {
  // Code that always gets executed
}

C#

Exception up 
  = new Exception("Something is really wrong."); 
throw up;  // ha ha

try {
  y = 0; 
  x = 10 / y;
} catch (Exception ex) { // 매개변수가 없어도 됨
  Console.WriteLine(ex.Message); 
} finally {
  // Code that always gets executed
}

C#의 catch 블록에서 매개변수를 생략할 수도 있다.

C#에서는 throws 키워드가 없다.

클래스 / 인터페이스

Java

접근 키워드
public
private
protected
static



// 상속
class FootballGame extends Competition {
  ...
}

// 인터페이스
interface IAlarmClock {
  ...
}

// 인터페이스의 상속
interface IAlarmClock extends IClock {
  ...
}

// 인터페이스 구현
class WristWatch implements IAlarmClock, ITimer {
   ...
}

C#

접근 키워드
public
private
internal
protected
protected internal
static

// 상속
class FootballGame : Competition {
  ...
}

// 인터페이스
interface IAlarmClock {
  ...
}

// 인터페이스의 상속
interface IAlarmClock : IClock {
  ...
}

// 인터페이스 구현
class WristWatch : IAlarmClock, ITimer {
   ...
}

Java의 기본 접근 제한자는 동일 패키지 내에서 접근 가능인 반면, C#에서는 private이다.

C#의 internal 키워드는 현재 어셈블리 내에서만 접근 가능하도록 지정하는 것이며, 어셈블리는 Java의 Jar파일과 유사한 개념이다.

Java에서 클래스가 더이상 상속 될 수 없도록 지정하는 final 키워드 대신, C#에서는 sealed 키워드를 사용한다.

Java에서 상속과 구현을 나타내는 키워드인 extends와 implements 대신, C#에서는 :을 사용한다.

Java의 super 키워드 대신, C#에서는 base 키워드를 사용한다.

Java와 달리, C#에서는 오버라이드 될 메서드에는 virtual 키워드를 오버라이드 하는 메서드에는 override 키워드를 사용한다.

C#에서는 인덱서를 지원하므로 이를 이용하면 클래스나 구조체를 배열처럼 다룰 수 있다.

객체

Java

SuperHero hero = new SuperHero();
hero.setName("SpamMan"); 
hero.setPowerLevel(3); 

hero.Defend("Laura Jones");
SuperHero.Rest();  // 정적 메서드 호출
SuperHero hero2 = hero;   // 동일한 객체를 참조

hero2.setName("WormWoman"); 
System.out.println(hero.getName()); 

hero = null;   // Free the object
if (hero == null)
  hero = new SuperHero();
Object obj = new SuperHero(); 
System.out.println("object's type: " + obj.getClass().toString()); 
if (obj instanceof SuperHero) 
  System.out.println("Is a SuperHero object.");

C#

SuperHero hero = new SuperHero(); 
hero.Name = "SpamMan"; 
hero.PowerLevel = 3;

hero.Defend("Laura Jones");
SuperHero.Rest();   // 정적 메서드 호출
SuperHero hero2 = hero;   // 동일한 객체를 참조
 
hero2.Name = "WormWoman"; 
Console.WriteLine(hero.Name);  

hero = null ;   // Free the object
if (hero == null)
  hero = new SuperHero();
Object obj = new SuperHero(); 
Console.WriteLine("object's type: " + obj.GetType().ToString()); 
if (obj is SuperHero) 
  Console.WriteLine("Is a SuperHero object.");

생성자 / 파괴자

Java

class SuperHero {
  private int mPowerLevel;

  public SuperHero() {
    mPowerLevel = 0;
  }

  public SuperHero(int powerLevel) {
    this.mPowerLevel= powerLevel;
  }

  // 파괴자는 없음
  protected void finalize() throws Throwable { 
    super.finalize();   // 항상 부모 요소를 호출
  }
}

C#

class SuperHero {
  private int mPowerLevel;

  public SuperHero() {
     mPowerLevel = 0;
  }

  public SuperHero(int powerLevel) {
    this.mPowerLevel= powerLevel; 
  }

  ~SuperHero() {
    // Destructor code to free unmanaged resources.
    // Implicitly creates a Finalize method.
  }
}

Java에서는 finalize() 메서드를 사용해서 가비지 컬렉터에 의해 인스턴스가 정리되기 직전에 실행될 메서드를 지정하는 반면, C#에서는 매개변수 없는 생성자와 유사한 형식으로 지정하며 이름 앞에 물결 표시(~)를 붙인다.

속성

Java

private int mSize;

public int getSize() { return mSize; } 
public void setSize(int value) {
  if (value < 0) 
    mSize = 0; 
  else 
    mSize = value; 
}


int s = shoe.getSize();
shoe.setSize(s+1);

C#

private int mSize;

public int Size { 
  get { return mSize; } 
  set { 
    if (value < 0) 
      mSize = 0; 
    else 
      mSize = value; 
  } 
}

shoe.Size++;

C#에서는 private 멤버 변수의 getter와 setter 메서드를 처리하는 get, set 키워드를 지원한다.

구조체

Java

x

C#

x

x

프로그램 구조

Java

 

C#

struct StudentRecord {
  public string name;
  public float gpa;

  public StudentRecord(string name, float gpa) {
    this.name = name;
    this.gpa = gpa;
  }
}

StudentRecord stu = new StudentRecord("Bob", 3.5f);
StudentRecord stu2 = stu;  

stu2.name = "Sue";
Console.WriteLine(stu.name);    // Prints "Bob"
Console.WriteLine(stu2.name);   // Prints "Sue"

C#에서는 클래스와 유사한 구조체라는 자료형을 지원한다. 단, 구조체는 상속이 불가능하고, 참조형 데이터가 아니다.

이벤트

Java

 

C#

window.ClickedEvent += MyEventHandler;

Java의 경우 이벤트를 수신할 클래스에서 Listener를 구현한 후 이벤트를 발생시키는 객체에 등록(register)하지만, C#에서 이벤트는 이벤트를 발생시키는 객체의 멤버이므로 이벤트 핸들러 메서드를 추가하기만 하면 된다.

C#에서는 이벤트 핸들러 메서드를 위해 delegate 키워드를 제공한다. 딜리게이트는 함수 포인터와 유사한 개념이다.

콘솔 입출력

Java

java.io.DataInput in 
= new java.io.DataInputStream(System.in);
System.out.print("What is your name? ");
String name = in.readLine();

System.out.print("How old are you? ");
int age = Integer.parseInt(in.readLine());
System.out.println(name + " is " + age + " years old.");
int c = System.in.read();   // Read single char
System.out.println(c);      // Prints 65 if user enters "A"

// The studio costs $499.00 for 3 months.
System.out.printf("The %s costs $%.2f for %d months.%n", "studio", 499.0, 3);

// Today is 06/25/04
System.out.printf("Today is %tD\n", new java.util.Date());

C#

Console.Write("What's your name? ");
string name = Console.ReadLine();



Console.Write("How old are you? ");
int age = Convert.ToInt32(Console.ReadLine());
Console.WriteLine("{0} is {1} years old.", name, age);
// 또는
Console.WriteLine(name + " is " + age + " years old.");
int c = Console.Read(); // Read single char Console.WriteLine(c); // Prints 65 if user enters "A" // The studio costs $499.00 for 3 months. Console.WriteLine("The {0} costs {1:C} for {2} months.\n",
"studio", 499.0, 3); // Today is 06/25/2004 Console.WriteLine("Today is " + DateTime.Now.ToShortDateString());

파일 입출력

Java

import java.io.*;

// Character stream writing
FileWriter writer 
  = new FileWriter("c:\\myfile.txt");
writer.write("Out to file.\n");
writer.close();

// Character stream reading
FileReader reader 
  = new FileReader("c:\\myfile.txt");
BufferedReader br = new BufferedReader(reader);
String line = br.readLine(); 
while (line != null) {
  System.out.println(line); 
  line = br.readLine(); 
} 
reader.close();

// Binary stream writing
FileOutputStream out 
  = new FileOutputStream("c:\\myfile.dat");
out.write("Text data".getBytes());
out.write(123);
out.close();

// Binary stream reading
FileInputStream in 
  = new FileInputStream("c:\\myfile.dat");
byte buff[] = new byte[9];
in.read(buff, 0, 9);   // Read first 9 bytes into buff
String s = new String(buff);
int num = in.read();   // Next is 123
in.close();

C#

using System.IO;

// Character stream writing
StreamWriter writer 
  = File.CreateText("c:\\myfile.txt"); 
writer.WriteLine("Out to file."); 
writer.Close();

// Character stream reading
StreamReader reader 
  = File.OpenText("c:\\myfile.txt"); 
string line = reader.ReadLine(); 
while (line != null) {
  Console.WriteLine(line); 
  line = reader.ReadLine(); 
} 
reader.Close();



// Binary stream writing
BinaryWriter out 
  = new BinaryWriter(File.OpenWrite("c:\\myfile.dat")); 
out.Write("Text data"); 
out.Write(123); 
out.Close();

// Binary stream reading
BinaryReader in 
  = new BinaryReader(File.OpenRead("c:\\myfile.dat")); 
string s = in.ReadString(); 
int num = in.ReadInt32(); 
in.Close();

C#에는 이 외에 인덱서, unsafe, fixed 등이 더 있음.

참고 자료:

http://www.harding.edu/fmccown/java_csharp_comparison.html

http://msdn.microsoft.com/en-us/library/ms228602(v=vs.90)

 


'C# > 문법 및 기능' 카테고리의 다른 글

C# 구조체(Struct)  (0) 2019.08.14
C# 접근 제한자(Access Modifier)  (0) 2019.08.13
C# NameValueCollection  (0) 2016.03.20
C# Dictionary 와 comboBox 연결  (0) 2016.02.08
C# Directory (폴더) 생성 및 삭제  (0) 2016.01.16
블로그 이미지

Link2Me

,
728x90

NameValueCollectionkey와 value를 모두 string으로 받아 보관하는 Collection이다. 

NameValueCollection strqry = new NameValueCollection()
{
  {"key1", "value1"},
  {"key2", "value2"},
  {"key3", "value3"}
};

아래 코드는 같은 결과를 3가지 경우로 보여주도록 처리된 예제를 만들었다.
상황에 따라 활용할 수 있게 하기 위해서다.

using System.Collections.Specialized; // NameValueCollection
private void btnSave_Click(object sender, EventArgs e)
{
NameValueCollection strqry = new NameValueCollection();
strqry.Add("Very High", "80");
strqry.Add("High", "60");
strqry.Add("medium", "50");
strqry.Add("Pass", "40");

foreach (string fieldName in strqry.Keys)
{
foreach (string fieldValue in strqry.GetValues(fieldName))
{
MessageBox.Show(fieldName + " - " + fieldValue);
}
}

foreach (string fieldName in strqry.Keys)
{
string fieldValue = strqry.Get(fieldName);
MessageBox.Show(fieldName + " - " + fieldValue);
}

for (int i = 0; i < strqry.Count; i++)
{
MessageBox.Show(i.ToString() + " : " + strqry.GetKey(i) + " - " + strqry.Get(i));
}
}

참고하면 도움될 사이트
http://www.c-sharpcorner.com/UploadFile/d3e4b1/practical-usage-of-namevaluecollection-in-C-Sharp-part1/



 


'C# > 문법 및 기능' 카테고리의 다른 글

C# 접근 제한자(Access Modifier)  (0) 2019.08.13
자바와 C#의 차이점  (0) 2016.12.27
C# Dictionary 와 comboBox 연결  (0) 2016.02.08
C# Directory (폴더) 생성 및 삭제  (0) 2016.01.16
C# 시간 메소드  (0) 2016.01.15
블로그 이미지

Link2Me

,
728x90

C# Dictionary 와 콤보박스 연결해서 값을 알아내는 걸 구글링하여 많은 예제를 보면서 경우 제대로 동작하는 걸 알게 되었다.

Dictionary 는 Hashtable 의 제네릭 버전이다.


콤보박스와 Binding 하는 소스는 쉽게 찾을 수 있다. 하지만 선택된 값이나 Key 값을 알아내는 걸 찾기가 쉽지 않았다.

comboBox1.SelectedItem 이 어떤 결과를 보여주는지는 코드를 직접 실행해보면서 확인하면 된다.


Dictionary <TKey, TValue> dic = new Dictionary <TKey, TValue>();

첫번째 아이템은 Key 이고, 두번째 아이템은 Value 이다.




using System;
using System.Collections.Generic;
using System.Windows.Forms;
 
namespace comboBox_Dictionary
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }
 
        private void Form1_Load(object sender, EventArgs e)
        {
            selectedcomboBox();
        }
 
        private void selectedcomboBox()
        {
            var cBox = new Dictionary<stringint>();
            cBox.Add("일요일",1);
            cBox.Add("월요일",2);
            cBox.Add("화요일",3);
            cBox.Add("수요일",4);
            cBox.Add("목요일",5);
            cBox.Add("금요일",6);
            cBox.Add("토요일",7);
 
            comboBox1.DataSource = new BindingSource(cBox, null);
            comboBox1.DisplayMember = "Key";
            comboBox1.ValueMember = "Value";
            comboBox1.SelectedValue = 5;
        }
 
        private void button1_Click(object sender, EventArgs e)
        {
            KeyValuePair<stringint> selectedPair = (KeyValuePair<stringint>)comboBox1.SelectedItem;
            textBox1.Text = string.Format("Selected Text : {0} and Value : {1}", selectedPair.Key, selectedPair.Value);
 
            //textBox1.Text = string.Format("Selected Text:{0} and Value:{1}",comboBox1.SelectedItem,comboBox1.SelectedValue);
 
        }
    }
}

첨부파일에는 코드가 약간 더 있다.


comboBox_Dictionary.zip



개발자가 아닌지라 자주 사용하지 않아 오래되면 기억이 나질 않는다.

그래서 추가로 알게된 사항을 기록해둔다.

동일한 함수를 여러번 호출해서 사용해야 할 경우가 있다.
이때는
selectedcomboBox(comboBox1) 으로 처리한다.
private void selectedcomboBox(ComboBox CB)
{
    var cBox = new Dictionary<string, int>();
    cBox.Add("일요일", 1);
    cBox.Add("월요일", 2);
    cBox.Add("화요일", 3);
    cBox.Add("수요일", 4);
    cBox.Add("목요일", 5);
    cBox.Add("금요일", 6);
    cBox.Add("토요일", 7);

    CB.DataSource = new BindingSource(cBox, null);
    CB.DisplayMember = "Key";
    CB.ValueMember = "Value";
    CB.SelectedValue = 5; // 몇번째 항목을 default 로 선택할 것인가?
}

자동으로 변경되는 값을 DB에서 가져와서 뿌려줘야 한다면
void cat1comboBox(ComboBox CB)
{
    CB.Items.Clear();
    CB.Items.Add("전체");
    try
    {
        myConn = new MySqlConnection(GetConnectionString());
        myConn.Open();

        string strqry = "select uid, classname from category where relateduid=0";
        strqry += " order by uid";
        adapter = new MySqlDataAdapter(strqry, myConn);
        DataSet cat1 = new DataSet();
        adapter.Fill(cat1);

        foreach (DataRow dr in cat1.Tables[0].Rows)
        {
            CB.Items.Add(dr["classname"]);
        }
        CB.SelectedIndex = 0; // 첫번째 아이템 선택
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.Message);
    }
    finally
    {
        this.myConn.Close();
    }
}

private void cat1comboBox1_SelectedIndexChanged(object sender, EventArgs e)
{
    cat2 = cat2comboBox(cat1comboBox1.SelectedItem.ToString(), cat2comboBox1); // 수정할 곳
    cat1name1 = cat1comboBox1.SelectedItem.ToString(); // TabPage1 의 cat1comboBox1

    myConn = new MySqlConnection(GetConnectionString());
    myConn.Open();

    string strqry = "select uid from category";
    strqry += " where relateduid=0 and classname='" + cat1name1 + "' "; // 수정할 곳

    MySqlCommand cmd = new MySqlCommand(strqry, myConn);
    cmd.CommandType = CommandType.Text;
    MySqlDataReader dr = cmd.ExecuteReader();
    while (dr.Read())
    {
        cat1uid1 = dr.GetString(0); // 수정할 곳
    }
    dr.Close();
    myConn.Close();
}


'C# > 문법 및 기능' 카테고리의 다른 글

자바와 C#의 차이점  (0) 2016.12.27
C# NameValueCollection  (0) 2016.03.20
C# Directory (폴더) 생성 및 삭제  (0) 2016.01.16
C# 시간 메소드  (0) 2016.01.15
C# 파일 입출력 개념 정리  (0) 2016.01.05
블로그 이미지

Link2Me

,
728x90

C# 에서 User Documnets 폴더 밑에다가 특정 폴더를 만들고 싶은 경우가 있다.

이때 간단하게 폴더를 생성하는 코드다.


private void MyFolderCreate(string myfolder)
{
    string UserPath = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments); // User Documents 폴더
    string MyPath = UserPath + "\\" + myfolder;
    if (!Directory.Exists(MyPath))
    {
        System.IO.Directory.CreateDirectory(MyPath);
    }
}


아래는 폴더 경로 정보와 폴더 생성를 분리하여 처리한 코드이다.

public static void MyFolderCreate(string myfolder)
{
    string MyPath = MyFolder(myfolder);
    if (!Directory.Exists(MyPath))
    {
        Directory.CreateDirectory(MyPath);
    }
}

public static string MyFolder(string myfolder)
{
    string UserPath = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments); // User Documents 폴더
    return UserPath + "\\" + myfolder;
}


=== 폴더 삭제 코드 ===


public static void MyFolderDelete(string path)
{
    DeleteDirectory(path, false);
}

public static void DeleteDirectory(string path, bool recursive)
{
    if (recursive)
    {
        var subfolders = Directory.GetDirectories(path);
        foreach (var subfolder in subfolders)
        {
            DeleteDirectory(subfolder, recursive);
        }
    }

    // Get all files of the folder
    var files = Directory.GetFiles(path);
    foreach (var file in files)
    {
        var attribute = File.GetAttributes(file);
        if ((attribute & FileAttributes.ReadOnly) == FileAttributes.ReadOnly)
        {
            File.SetAttributes(file, attribute ^ FileAttributes.ReadOnly);
        }
        File.Delete(file);
    }
    Directory.Delete(path);
}


폴더 삭제코드 출처 : http://caioproiete.net/en/csharp-delete-folder-including-its-sub-folders-and-files-even-if-marked-as-read-only/


'C# > 문법 및 기능' 카테고리의 다른 글

C# NameValueCollection  (0) 2016.03.20
C# Dictionary 와 comboBox 연결  (0) 2016.02.08
C# 시간 메소드  (0) 2016.01.15
C# 파일 입출력 개념 정리  (0) 2016.01.05
C# int.TryParse  (0) 2015.12.25
블로그 이미지

Link2Me

,
728x90

C# 에서 시간을 다루는 메소드가 몇가지 있다.

활용하는 목적이 좀 다르다.


System.Windows.Forms 을 이용하여 타이머를 구동시키는 경우에는 함수가 실행될 때 타이머가 동작하고 함수가 종료되면 타이머를 멈추는 방식이다.

using System.Windows.Forms;
private void MainForm_Load(object sender, EventArgs e)
{
    timer1.Interval = 60000;  // 지정단위는 millisecond
    timer1.Start();   // 다른 방법으로는 timer1.Enabled = true; 라고 하면 된다
}

private void timer1_Tick(object sender, EventArgs e)
{
    //현재 시각을 가져와 time 변수에 할당
    DateTime time = DateTime.Now// 현재 날짜와 시간을 얻는다
    if (time.Hour == 09 && time.Minute == 10)
    {  //time 변수의 시가 09시이고, 분이 10이면 코드 실행
        // 실행할 코드
        timer1.Stop();
    }
}


C#에서 시간에 대한 데이타형은 2종류다.
DateTime과 TimeSpan
DateTime 구조체는 날짜와 시간을 표현한다. 2016년 1월 10일 이렇게 시각을 정할때 사용하고
TimeSpan은 두 시점간의 간격을 경과일과 시분초로 표현하며, 정밀도는 천만분의 1초이다.

시간으로 10일을 더하고 싶으면 TimeSpan.FromDays(10)이렇게 하면 10일을 tick으로 환산하여 계산한다.
// DateTime(년,월,일,시,분,초)
DateTime birthday = new DateTime(1997,04,21,19,05,30);
//시각(DateTime) - 시각 = 시간(TimeSpan)
TimeSpan result = DateTime.Now - birthday;


// 현재 날짜와 시간을 출력하고자 할 경우 출력하는 형태를 지정해서 할 수 있다

DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss");


소요(동작)시간 체크하기

System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();  // Stopwatch 객체 생성
sw.Start();
OpenSubtitle(fileName, listView1); // 체크하고 싶은 메소드
sw.Stop();

// 동작시간 출력

MessageBox.Show(sw.Elapsed.ToString());


// 동작시간을 밀리초 단위로 출력

MessageBox.Show(sw.ElapsedMilliseconds.ToString() + " msec");


또다른 소요시간 체크하는 방법

var start = DateTime.Now;
OpenSubtitle(fileName, listView1);
var stop = DateTime.Now - start;
MessageBox.Show("소요시간:" + stop.ToString());

사용자 지정 날짜 및 시간 형식 문자열 MSDN : https://msdn.microsoft.com/ko-kr/library/8kb3ddd4%28v=vs.110%29.aspx




'C# > 문법 및 기능' 카테고리의 다른 글

C# Dictionary 와 comboBox 연결  (0) 2016.02.08
C# Directory (폴더) 생성 및 삭제  (0) 2016.01.16
C# 파일 입출력 개념 정리  (0) 2016.01.05
C# int.TryParse  (0) 2015.12.25
C# 오버라이딩(Overriding) 개념 이해  (1) 2015.12.21
블로그 이미지

Link2Me

,
728x90

데이터를 읽고 쓰기 위해 C# 에서는 stream(스트림) 객체를 사용한다.

닷넷의 스트림 관련 클래스들은 System.IO 네임스페이스에 정의되어 있다.


HDD(하드디스크), SSD 에 있는 파일을 읽고 쓰는데 사용되는 기본 클래스는 FileStream 이다.


var fs = new FileStream(srcFile, FileMode.Open, FileAccess.Read, FileShare.Read);

- srcFile : 파일의 경로 + 파일명

- FileMode : https://msdn.microsoft.com/ko-kr/library/system.io.filemode%28v=vs.110%29.aspx

- FileAccess : https://msdn.microsoft.com/ko-kr/library/4z36sx0f%28v=vs.110%29.aspx

- FileShare : https://msdn.microsoft.com/ko-kr/library/system.io.fileshare%28v=vs.110%29.aspx


byte[] buffer = new byte[4]; // 스트림으로부터 읽은 데이터를 저장할 크기가 4인 바이트 배열 버퍼
var fs = new FileStream(srcFile, FileMode.Open, FileAccess.Read, FileShare.Read);
fs.Read(buffer, 0, 4);
fs.Close();


byte[] buffer;
using (var fs = File.Open(srcFile, FileMode.Open))
{
    buffer = new byte[fs.Length];
    fs.Read(buffer, 0, (int)fs.Length);   
}


buffersize : 스트림을 입출력 효율 향상을 위해 버퍼를 사용한다.

HDD 에서 블럭 단위로 몽땅 읽어와 버퍼에 쌓아두고 다음에 읽을 때는 버퍼에서 읽어 입출력 속도가 향상된다.


FileStream 은 입출력 대상이 byte 배열로 고정되어 있어 실제 사용하기에는 불편하다.

응용 프로그램은 문자열, 실수, 정수와 같은 고수준 타입을 다루는 경우가 더 많다.

텍스트파일은 아주 단순한 구조로 되어 있지만 인코딩 방식에 따라 ANSI, UTF8, Unicode, UTF7 등 여러가지 포멧이 있다. 파일을 읽어올 때 인코딩 방식을 잘못 읽어오면 파일이 깨질 수 있다.

닷넷은 입출력 과정에서 자동으로 문자열 변환을 수행하는 StreamReader, StreamWriter 클래스를 제공한다.

using 문은 자동으로 해당 코드를 수행한 후 스트림의 Dispose() 메소드를 호출한다. using 문을 사용하면 스트림이 닫히지 않는 상태에서 해당 파일을 사용하려고 할 때 발생하는 버그를 걱정하지 않아도 된다.


//인코딩
C# 에서의 자료형을 갖는 데이터 -> 스트림(byte[])
EUC-KR(ANSI, MS949)
  - 영어(숫자,특수) 1칸
  - 한글 2칸
UTF-8(C#의 기본 인코딩 방식)
  - 영어(숫자,특수) 1칸
  - 한글 3칸
UTF-16
  - 영어(숫자,특수) 2칸
  - 한글 2칸


using (StreamReader sr = new StreamReader(fileName, System.Text.Encoding.UTF8))
{
    readText = sr.ReadToEnd();
    sr.Dispose();
}


HttpWebResponse response = (HttpWebResponse)request.GetResponse();
StreamReader readerPost = new StreamReader(response.GetResponseStream(), System.Text.Encoding.UTF8, true);
resResult = readerPost.ReadToEnd();

readerPost.Close();

string txt = string.Empty;
while ((txt = result.ReadLine()) != null)  // 한줄씩 읽어서 구분자로 나눠서 배열로 담아서 처리
{
    //1. 파싱
    string[] item = txt.Split(';');
    //2. Member 배열 객체 생성, m 은 참조변수
    Member m = new Member(item[0], item[1], item[2], item[3]);
    //3. Member 배열(ArrayList) 삽입
    list.Add(m);
} //while
result.Close();


using(Stream stream = File.Create(fileName))
{
    using (var textExport = new StreamWriter(stream, Encoding.UTF8))
    {
        foreach (ListViewItem row in LV.Items)
        {
            textExport.WriteLine(row.SubItems[0].Text);
            textExport.WriteLine(row.SubItems[1].Text);
            textExport.Write(Environment.NewLine);
        }

        textExport.Flush(); // flush from the buffers
        textExport.Close();
    }
}


여러 객체에 대해서는 여러개의 using 문을 사용하면 된다.

위의 코드에 using 을 두번 사용하고 중괄호{} 두번 사용했는데 첫번째 것은 중괄호를 생략해도 된다.

using(Stream stream = File.Create(fileName))
using (var textExport = new StreamWriter(stream, Encoding.UTF8))
{
    foreach (ListViewItem row in LV.Items)
    {
        textExport.WriteLine(row.SubItems[0].Text);
        textExport.WriteLine(row.SubItems[1].Text);
        textExport.Write(Environment.NewLine);
    }

    textExport.Flush(); // flush from the buffers
    textExport.Close();
}

클래스나 구조체같은 복잡한 이진 데이터를 저장할 때는 BinaryReader, BinaryWriter 클래스를 사용한다.

아직 이걸로 작성해본 것이 없어서 다음에 작성하게 되면 자료를 추가 보완할 예정


MemoryStream 참조하면 도움되는 사이트 http://net-informations.com/q/faq/memory.html


'C# > 문법 및 기능' 카테고리의 다른 글

C# Directory (폴더) 생성 및 삭제  (0) 2016.01.16
C# 시간 메소드  (0) 2016.01.15
C# int.TryParse  (0) 2015.12.25
C# 오버라이딩(Overriding) 개념 이해  (1) 2015.12.21
C# 메소드 오버로딩 개념잡기  (0) 2015.12.21
블로그 이미지

Link2Me

,
728x90

int.PryParse(string str, out int result) 는 문자열(string)을  숫자로 변환할 때 사용한다.

str : 변환할 숫자가 포함된 문자열

result : 변환이 성공한 경우 str에 포함된 숫자의 정수 값을 반환하고, 변환이 실패한 경우 0을 반환

int 대신에 double, int32 를 쓸 수도 있다.


string Str = Console.ReadLine();
double Num;
bool isNum = double.TryParse(Str, out Num);
if (isNum) {
    Num = Num * 2.54;
    Console.WriteLine(Num + "cm");
}
else {
     Console.WriteLine("Invalid number");
}


private void listView_CellUpdate(ListView LV)
{
    int value = 0;
    foreach (ListViewItem row in LV.Items)
    {
        int.TryParse(row.SubItems[5].Text, out value);
        if (value == 10)
        {
            row.SubItems[4].Text = "보통";
        }
    }
}


private void dataGridView_CellUpdate()
{
    int value = 0;
    for (int row = 0; row < dataGridView1.Rows.Count; row++)
    {
        int.TryParse(dataGridView1.Rows[row].Cells[5].Value.ToString(), out value);
        if (value == 10)
        {
            dataGridView1.Rows[row].Cells[5].Value = 6000;
        }
    }
}

'C# > 문법 및 기능' 카테고리의 다른 글

C# 시간 메소드  (0) 2016.01.15
C# 파일 입출력 개념 정리  (0) 2016.01.05
C# 오버라이딩(Overriding) 개념 이해  (1) 2015.12.21
C# 메소드 오버로딩 개념잡기  (0) 2015.12.21
C# List 개념 이해 -1  (0) 2015.12.14
블로그 이미지

Link2Me

,
728x90

상속(Inheritance) : 부모 클래스에 정의된 데이터 및 메소드들을 파생클래스에서 이용할  수 있는 기능을  상속이라고 한다.

C#에서 파생클래스를 정의하기 위해서는 클래스명 뒤에 Colon (:)을 찍고 Base 클래스명을 써 주면 된다. 제약점은 C#에서는 파생클래스가 단 하나의 Base 클래스로부터 상속되어져야 한다는 것이다. 즉, 하나의 파생클래스는 2개 이상의 Base 클래스를 가질 수 없다.


오버로딩(Overloading)은 한 클래스 내에서 동일한 이름의 메서드를 추가 정의하는 것이다.

반면에 오버라이딩(Overriding)은 클래스간 상속 관계에서 메서드를 재 정의하는 기법이다.


두 클래스가 상속 관계에 있으면 부모 클래스의 public, protected 으로 선언된 메서드는 자식 클래스로 그대로 상속되어 자식클래스에서 사용이 가능하게 된다. 즉 이미 정의된 메서드를 재 사용하게 되는 것이다.

메서드를 오버라이딩 할 때 부모 클래스에서는 virtual 로, 자식 클래스에서는 override 키워드로 메서드를 정의해야 한다.


방법 1 : 부모 클래스에 virtual, 자식 클래스에 override 키워드를 사용하는 경우

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

namespace Override
{
    class BaseClass // 부모 클래스
    {
        public virtual void MethodA() // 부모클래스의 MethodA 메소드
        {
            Console.WriteLine("In the BaseClass ...");
            // 부모클래스로 객체를 생성하고 MethodA 메소드를 호출하면 이 문구가 출력
        }
    }
    class DerivedClass : BaseClass // DerivedClass (자식) 클래스는 BaseClass(부모클래스)를 상속받는다
    {
        public override void MethodA()
        {
            // 부모클래스와 동일 메소드(매개변수 똑같음)를 자식 클래스에서 생성하는것을 오버라이딩이라고 한다.
            Console.WriteLine("In DerivedClass ... Overriding !!!");
            // DerivedClass클래스로 객체를 생성하고 MethodA를 호출하면 이 문구가 출력된다
        }
        public void MethodA(int i) // 이경우는 메소드 이름은 같은데 매개변수가 다르다. int형 변수가 입력될 경우 이 메소드가 실행된다.
        {
            // Overloading : 메소드 이름은 동일하고 매개변수가 다른경우를 오버로딩이라고 한다.
            Console.WriteLine("In DerivedClass ... Overloading !!!");
            // Derivedclass클래스로 객체를 생성하고 MethodA메소드에 매개변수(int형)을 포함해 호출하면 이 문구가 출력된다.
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            BaseClass parent = new BaseClass(); // Baseclass(부모) 클래스로 새 객체를 생성한다.
            DerivedClass child = new DerivedClass(); // DerivedClass(자식) 클래스로 새 객체를 생성한다.
            parent.MethodA(); // 부모 객체에서 MethodA 메소드 호출 -> In the BaseClass ... 출력
            child.MethodA(); // 자식 객체에서 MethodA 메소드 호출 -> In DerivedClass ... Overriding !!! 출력
            child.MethodA(1); // 자식 객체에서 MethodA(1) 메소드 호출 -> In DerivedClass ... Overloading!!! 출력
        }
    }
}



방법 2 : 부모 클래스에 virtual 를 미정의 시, 자식 클래스에서 메소드 앞에 new를 붙이면 된다.

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

namespace Override
{
    class BaseClass // 부모 클래스
    {
        public void MethodA() // 부모클래스의 MethodA 메소드
        {
            Console.WriteLine("In the BaseClass ...");
            // 부모클래스로 객체를 생성하고 MethodA 메소드를 호출하면 이 문구가 출력
        }
    }
    class DerivedClass : BaseClass // DerivedClass (자식)클래스는 BaseClass(부모클래스)를 상속받는다
    {
        new public void MethodA()
        {
            // 부모클래스의 MethodA 와 이름이 똑같은데 new 를 붙이면 부모클래스의 메소드를 덮어씌운다.

            // new 를 통해 메서드를 재 정의하게 되면 부모 클래스의 원 메서드는 숨기게(가려지게) 된다.

            // 부모클래스와 동일 메소드(매개변수 똑같음)를 자식 클래스에서 생성하는것을 오버라이딩
            Console.WriteLine("In DerivedClass ... Overriding !!!");
            // DerivedClass클래스로 객체를 생성하고 MethodA를 호출하면 이 문구가 출력된다
        }
        public void MethodA(int i) // 이경우는 메소드 이름은 같은데 매개변수가 다르다. int형 변수가 입력될 경우 이 메소드가 실행된다.
        {
            // Overloading : 메소드 이름은 동일하고 매개변수가 다른경우를 오버로딩이라고 한다.
            Console.WriteLine("In DerivedClass ... Overloading !!!");
            // Derivedclass클래스로 객체를 생성하고 MethodA메소드에 매개변수(int형)을 포함해 호출하면 이 문구가 출력된다.
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            BaseClass parent = new BaseClass(); // Baseclass(부모) 클래스로 새 객체를 생성한다.
            DerivedClass child = new DerivedClass(); // DerivedClass(자식) 클래스로 새 객체를 생성한다.
            parent.MethodA(); // 부모 객체에서 MethodA 메소드 호출 -> In the BaseClass ... 출력
            child.MethodA(); // 자식 객체에서 MethodA 메소드 호출 -> In DerivedClass ... Overriding !!! 출력
            child.MethodA(1); // 자식 객체에서 MethodA(1) 메소드 호출 -> In DerivedClass ... Overloading!!! 출력
        }
    }
}
 


실행결과


자식 클래스의 메소드 앞에 new를 붙이지 않았을 경우


오류목록에 숨기려면 new 를 붙이라고 에러 메시지를 보여준다.


예제로 사용한 코드


Override.zip



참고하면 좋은 글

ㅇ 클래스의 상속 : https://blog.hexabrain.net/142


'C# > 문법 및 기능' 카테고리의 다른 글

C# 파일 입출력 개념 정리  (0) 2016.01.05
C# int.TryParse  (0) 2015.12.25
C# 메소드 오버로딩 개념잡기  (0) 2015.12.21
C# List 개념 이해 -1  (0) 2015.12.14
C# 배열 개념 이해 및 실전 응용  (0) 2015.12.13
블로그 이미지

Link2Me

,
728x90

C# 에서 함수(메소드)는 동일한 것을 여러개 만들 수가 있다는 걸 알게 되었다.

유투브 동영상 강좌를 보고, 구글링으로 얻은 지식 중에서 핵심내용만 적어두려고 한다.


오버로딩(OverLoading) : 한 클래스 내에서 동일한 이름의 메서드(함수)를 추가 정의



하나의 클래스에 같은 이름을 가진 메소드(함수)를 여러개 정의 할 수 있다.

메소드 이름은 동일하지만 시그너처의 갯수는 다르게 할 수 있다.

시그너처를 유일하게 하면 메서드의 이름은 얼마든지 같을 수 있다



public class MathClass
{
    public static int Max(int i, int j)
    {
        return i > j ? i : j;     //둘 중 큰수를 반환한다
    }
    public static int Max(int i, int j, int k)
    {
        return Max(Max(i, j), k); //Max(int, int) 를 호출한다
    }
    public static int Max(int i, int j, int k, int l)
    {
        return Max(Max(i, j, k), l); //Max(int, int, int) 를 호출한다
    }
    public static int Max(int[] arrays)
    {
        int maxValue = 0;
        foreach (int i in arrays)
        {
            maxValue = Max(maxValue, i); //Max(int,int) 를 호출한다
        }
        return maxValue;
    }
}




시그너처가 다르면 에러가 발생하지 않는다.


메소드 앞의 타입(string, int, double) 은 달라도 시그너처가 같으면 에러가 발생한다.




'C# > 문법 및 기능' 카테고리의 다른 글

C# int.TryParse  (0) 2015.12.25
C# 오버라이딩(Overriding) 개념 이해  (1) 2015.12.21
C# List 개념 이해 -1  (0) 2015.12.14
C# 배열 개념 이해 및 실전 응용  (0) 2015.12.13
C# Trackbar 기능 및 타이머 연결  (0) 2015.12.08
블로그 이미지

Link2Me

,
728x90

C# List 는 동적으로 할당하는 가변배열(동적배열)이라고 볼 수 있는데 좀 더 강력하다.

List 클래스는 닷넷 프레임워크를 바탕으로 만들어져 있어서 배열로는 할 수 없는 다양한 것을 할 수 있다.


List <T> 변수명 = new List <T>();


T에 원하는 타입을 지정하면 치환이 가능하다.

int, float, string 외에 어떠한 형태의 타입도 지정이 가능하다.


보통 예제가 콘솔에 뿌리는 형태인데 난 그냥 폼에 뿌리는 방식으로 해봤다.


using System;
using System.Collections.Generic;  // 리스트 사용하기 위해
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
 
namespace List
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }
 
        private void button1_Click(object sender, EventArgs e)
        {
            List<int> number = new List<int>();
 
            number.Add(10);  // 리스트 추가
            number.Add(20);  // 리스트 추가
            number.Add(30);  // 리스트 추가
            number.Add(40);  // 리스트 추가
 
            var sb = new StringBuilder();
            foreach (var item in number)
            {
                sb.AppendLine(item.ToString());                
            }
            textBox1.Text = sb.ToString();
 
            number.Remove(30); // 리스트 삭제
            number.RemoveAt(1); // 해당 인덱스의 리스트 삭제
            number.Insert(0100); // 0번째 인덱스에 100 추가
 
            sb = null;  // 변수 초기화
            sb = new StringBuilder(); // 메모리 재할당
            for (int i = 0; i < number.Count; i++)
            {
                sb.AppendLine(number[i].ToString());
            }
            MessageBox.Show(sb.ToString());
        }
    }
}


실행결과는 아래와 같다.

텍스트박스에 뿌리기 위해 StringBuilder 를 이용하여 값을 합쳐나갔고,

리스트를 삭제, 삽입하는 결과는 메시지박스에 표시되도록 했다.

소스코드를 복사해서 http://colorscripter.com/ 에 붙여넣기를 하고 언어를 C#을 선택한 다음, 클립보드에 복사를 선택하여 붙여넣기를 하면 된다.


배열과 달리 리스트는 원하는 곳에 데이터를 추가(Insert)할 수도 있다.

필요할 때마다 Add 를 사용해서 리스트를 추가해주고

Remove 나 RemoveAt 을 이용하여 리스트를 삭제할 수 있다.

삭제가 되면 리스트의 index 는 자동으로 하나씩 당겨진다.

배열에서 카운트는 number.Length 인데, 리스트에서는 number.Count 이다.



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
        private void button2_Click(object sender, EventArgs e)        {
            int[] arr = new int[3]; // New array with 3 elements.
            arr[0= 2;
            arr[1= 3;
            arr[2= 5;
 
            List<int> number = new List<int>(arr); // 배열을 리스트에 복사
        }
 
        private void button3_Click(object sender, EventArgs e)
        {
            List<int> number = new List<int>();
 
            number.Add(10);  // 리스트 추가
            number.Add(20);  // 리스트 추가
            number.Add(30);  // 리스트 추가
            number.Add(40);  // 리스트 추가
 
            int[] arr = number.ToArray(); // 일반 배열로 반환
        }
cs


List 객체는 어떤 유형이든 저장할 수 있다.

List<T> MSDN : https://msdn.microsoft.com/ko-kr/library/6sh2ey19%28v=vs.110%29.aspx

에서 다양한 기능을 확인할 수 있다.

블로그 이미지

Link2Me

,
728x90

배열 : 같은 형식의 여러개의 요소를 가지는 데이터 구조


배열을 선언할 때에는 유형(int, string, float 등) 바로 뒤에 꺽쇠 괄호를 붙인다.

int[] arr1;  // arr1 라는 참조변수는 null 로 설정된다.

 * 배열 선언문은 배열형 변수를 선언하는 것이지, 메모리를 할당하는 것은 아니다.

    배열은 참조형이므로 변수 자체가 실제 데이터를 저장하지 않는다.

arr1 = new int[5];  // 배열은 객체이므로 new 키워드를 써서 배열 객체를 생성

  * 배열 뿐만 아니라 모든 참조형은 new 연산자로 실제 메모리를 할당받아야 한다.


선언문과 할당문을 두 줄로 쓰는 것이 번거롭다면 int[] arr1 = new int[5]; 로 해도 된다.


[5] 꺽쇠 괄호안에 들어가는 숫자를 index 라고 부르며, 배열에서 index 는 0부터 시작한다.

int[] arr1 = new int[] { 1, 2, 3, 4, 5} 처럼 초기값을 할당할 수도 있다.

배열의 길이 5를 생략한 경우로, 이 경우에는 배열의 각 인덱스의 개수는 자동으로 세어준다.


텍스트 파일을 읽어서 Split 키워드를 이용해서 분할하여 배열로 담아야 하는 경우에는 배열의 크기를 알 수가 없는 경우가 대부분이다.

string[] strs = readText.Split(new string[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries);

줄바꿈(\r\n) 구분자로 분할해서 배열 변수 strs 에 담으라는 의미다. (Android 에서 줄바꿈은 \n )

strs.Lenght ; // 배열의 길이를 반환


문자열을 문자 배열로 만들고 싶을 때에는

string text = "My Array Test";

char[] Text = text.ToCharArray(); // 문자열을 문자 배열로 변경

배열 변수 사용중 초기화가 필요한 시점에서 아래 명령어로 초기화를 해준다.

Array.Clear(strs, 0, strs.Length);  // 배열 초기화

  * 배열은 일부러 해제하지 않아도 닷넷라이브러리에 쓰레기 수집 기능이 있어서

    더 이상 사용하지 않는 배열은 해제된다.

    배열 뿐만 아니라 모든 참조형에 공통적으로 적용되는 사항이다.

  * 배열 초기화를 해주는 이유는 배열을 사용하고 다시 다른 배열로 일부만 복사하여 사용하다보니

    처리속도가 늦어지는 것 같아서 배열을 바로 바로 초기화를 해주었더니 속도가 엄청 빨라졌다.


Array.Reverse(strs); // 배열 인덱스 뒤집기는 Array.Reverse(배열명) 을 사용한다

Array.Sort(strs); // 배열 소팅은 Array.Sort(배열명)을 사용한다.


배열 복사를 하고 싶을 때에는

string[] strs = readText.Split(new string[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries);

string[] copy_strs = new string[strs.Lenght];

Array.Copy(strs, copy_strs, strs.Length);


그런데 배열 복사의 index 수가 다르고, 갯수를 정확하게 파악하기 어려운 경우라면 어떻게 복사를 해야 할까?

아래 코드는 smi 자막을 파싱하여 읽어들이기 위해 만든 코드이다.

로직 순서는

1. 파일을 끝까지 읽어들인다.

2. 원하는 부분을 Split 으로 잘라낸다.

3. 잘라낸 부분을 배열로 담는다.

4. 배열로 담긴 부분에서 부분적으로 원하는 자료를 추출하기 위해

    StringBuilder 를 이용하여 조건에 맞는 배열을 합쳐서 하나의 파일로 만든다.

5. 다시 원하는 결과를 뽑아내기 위해 Split 으로 분리한다.


string[] bodyseparator = new string[1] { "<SYNC Start=" };
string[] bodyLines = bodyinfo.Split(bodyseparator, StringSplitOptions.RemoveEmptyEntries);
bodyinfo = null;  // 배열로 전달한 값은 초기화

var sb1 = new StringBuilder();
var sb2 = new StringBuilder();

for (int i = 1; i < bodyLines.Length; i++)
{
    if (bodyLines[i].Contains(ClassName1))
    {
        sb1.Append("<SYNC Start=" + bodyLines[i]);
    }

    if (bodyLines[i].Contains(ClassName2))
    {
        sb2.Append("<SYNC Start=" + bodyLines[i]);
    }
}
Array.Clear(bodyLines, 0, bodyLines.Length);  // 배열 초기화


아직 List 개념만 익힌 상태라서 실전 활용을 못해봐서 좀 무식하게 처리했을 수도 있다.

하나씩 기능을 익히면서 최적화된 코드를 만들 수 있는 날이 오겠지.....

블로그 이미지

Link2Me

,
728x90

Trackbar.Scroll 은 마우스나 키보드 조작을 통해 스크롤 상자가 이동될 때 발생한다.
TrackBar.ValueChanged : 트랙 표시줄의 Value 속성이 스크롤 상자 이동이나 코드 조작을 통해 변경될 때 발생



private void trackBar1_Scroll(object sender, EventArgs e)
{
    label1.Text = trackBar1.Value.ToString();
}


위 경우에는 마우스로 수동으로 Scroll 바를 움직여서 값을 변동되게 하는 방법이다.


Timer 와 연결해서 Trackbar 가 자동으로 움직이게 하려면

도구상자에게 timer 를 선택해서 Form에 Drag & Drop 한다.

그리고 timer1 이벤트를 생성한다.


private void timer1_Tick(object sender, EventArgs e)
{
    timer1.Enabled = true;
    trackBar1.Value += 1;
    if (trackBar1.Value >= trackBar1.Maximum) timer1.Enabled = false;
    label1.Text = trackBar1.Value.ToString();
}


타이머를 ON 하고 trackBar1 의 값이 1씩 증가하도록 등록한다.

trackBar1 의 최대값을 넘어가면 타이머를 종료시킨다.

그리고 변동되는 값을 label1.Text 에 기록한다.


MP3 플레이에서 노래가 재생될 때 구동시키려고 배우고 있는 중이다.


노래와 연결한다고 하면 아래와 같은 것이 필요하지 않을까 싶다.

trackBar1.Maximum 의 값은 100 으로 놓는다.

lbl_Time.Text = "00:00";  // 노래 한곡의 전체 재생시간

lbl_Duration.Text = "00:00";  // 플레이되는 동안의 시간 표시


Play 상태에서는

timer1.Enabled = true;

PlayState = true;


Stop 상태에서는

timer1.Enabled = false;

PlayState = false;

trackBar1.Value = 0;


이 밖에 또 뭐가 필요할지, 어떻게 구현해야 할지는 좀 더 샘플을 찾아보고 정리를 해보려고 한다.

초보자라 갈 길이 참으로 멀다.


블로그 이미지

Link2Me

,
728x90

지정된 형식에 따라 개체의 값을 문자열로 변환하여 다른 문자열에 삽입한다.

string.Format("{0};{1};{2};{3};{4};{5}",textBox1.Text.Trim(), textBox2.Text.Trim(), textBox3.Text.Trim(), textBox4.Text.Trim(), textBox5.Text.Trim(), textBox6.Text.Trim());


숫자형식 포맷팅을 이용하면 숫자로 이루어진 문자열을 다양한 형태로 출력 할 수 있다.

기본적으로 이 포맷팅은 System. String.Format 매서드에 기반하여 적용된다.


형식지정자

종류

예제코드

출력결과

C / c

통화
Currency

 Response.Write(string.Format("{0:C}", 2.5));

₩3

 Response.Write(string.Format("{0:C}", -3.5));

-₩4

D / d

10진법
Decimal

 Response.Write(string.Format("{0:D}", 00035));

35

E / e

과학적지수
Scientific

 Response.Write(string.Format("{0:E}", 342));

3.420000E+02

F / f

고정 소수점
Fixed-point

 Response.Write(string.Format("{0:F2}", 35.22));

35.22

 Response.Write(string.Format("{0:F0}", 35.22));

35

G / g

일반
General

 Response.Write(string.Format("{0:G}", 123456));

123456

N / n

숫자
Number

 Response.Write(string.Format("{0:N}", 25000000));

25,000,000.00

P / p

백분율
Percentage

 Response.Write(string.Format("{0:P}", .21548));

21.55%

 Response.Write(string.Format("{0:P1}", .112345));

11.2%

X / x

16진법
Hexadecimal

 Response.Write(string.Format("{0:X}", 250));

FA

 Response.Write(string.Format("{0:X}", 0xffff));

FFFF


출처 : http://www.dreamy.pe.kr/zbxe/CodeClip/157656


http://ryuschool.tistory.com/entry/C-%EB%AC%B8%EC%9E%90%EC%97%B4-StringFormat


이곳에 가면 String.Format 에 대한 샘플이 있으니 참고하면 된다.

http://www.csharp-examples.net/string-format-double/


블로그 이미지

Link2Me

,
728x90

C# 에서 %를 구하는 함수다.

구글링하면 온갖 함수들이 나오는데 시간낭비다.

제공되는 Math.Round 함수를 이용하면 한줄이면 된다.


private double GetPercentage(double value, double total, int decimalplaces)
{
    return System.Math.Round(value * 100 / total, decimalplaces) ;
}


사용예제

string.Format("입력 : {0} (전체의 {1}%)", cnt, GetPercentage(cnt,DBtotalcnt(),2));

블로그 이미지

Link2Me

,
728x90

C#에서 파일을 다중으로 선택하여 가져오기를 하는 코드이다.


MP3 파일을 다중으로 선택하여 가져오기를 할 경우에 적용해본 코드이다.


private void MP3File_Open()
{
    using (OpenFileDialog dlgOpen = new OpenFileDialog())
    {
        dlgOpen.Filter = "MP3 File|*.mp3";
        dlgOpen.Title = "Select Audio File";
        dlgOpen.Multiselect = true; // 파일 다중 선택
        //dlgOpen.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyMusic);
        if (dlgOpen.ShowDialog() == DialogResult.OK)
        {
            for (int i = 0; i < dlgOpen.FileNames.Length; i++)
            {
                FileOpen_ListView(dlgOpen.FileNames[i], listView1);
            }
        }
    }
}


private void FileOpen_ListView(string fileName, ListView LV)
{
    if (File.Exists(fileName))
    {
        if (Path.GetExtension(fileName).ToLower() == ".mp3")
        {
            Load_MP3(fileName, LV);
        }     
    }
}



for 문 대신에 foreach 문을 사용하면 .....

private void MP3File_Open()
{
    using (OpenFileDialog dlgOpen = new OpenFileDialog())
    {
        dlgOpen.Filter = "MP3 File|*.mp3";
        dlgOpen.Title = "Select Audio File";
        dlgOpen.Multiselect = true; // 파일 다중 선택
        if (dlgOpen.ShowDialog() == DialogResult.OK)
        {
            foreach (string file in dlgOpen.FileNames)
            {
                try
                {
                    FileOpen_ListView(file, listView1);
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message);
                }
            }
        }
    }
}



블로그 이미지

Link2Me

,
728x90
파일명 변경은 System.IO.File.Move(oldname, newname);

파일명 복사는 System.IO.File.Copy(oldname, newname);


oldFileName 은 파일경로와 파일명이 포함된 문자열


private string FileCopy(string oldFileName)
{
    string filePath = Path.GetDirectoryName(oldFileName);  // 파일 경로
    string filename_without_ext = Path.GetFileNameWithoutExtension(oldFileName);  // 파일 이름
    string ext_only = Path.GetExtension(oldFileName);  // 파일 확장자
    string newFileName = filePath + "\\" + filename_without_ext + "_Temp" + ext_only;
    if (File.Exists(newFileName))  // 파일의 존재 유무 확인 : 파일이 존재하면
    {
        string message = string.Format("{0} 파일이 이미 있습니다. 바꾸시겠습니까?", Path.GetFileName(newFileName));
        DialogResult dialogResult = MessageBox.Show(message, "알림", MessageBoxButtons.YesNo);
        if (dialogResult == DialogResult.Yes)
        {
            File.Delete(newFileName);  // 존재하는 파일 삭제
            File.Copy(oldFileName, newFileName);
        }
        else
        {
            DialogResult changeResult = MessageBox.Show("다른 파일로 변경하시겠습니까?", "알림", MessageBoxButtons.YesNo);
            if (changeResult == DialogResult.Yes)
            {
                SaveAsFile(listView2);  // SaveDialog 를 이용한 파일 저장
            }
            else
            {
                MessageBox.Show("파일명 변경을 취소하셨습니다");
            }
            newFileName = string.Empty;  // SaveAsFile 함수에서 이미 파일명 변경했거나 저장 취소
        }
    }
    else  
// 파일의 존재하지 않으면   

   {
        File.Copy(oldFileName, newFileName);
    }
    return newFileName;
}

블로그 이미지

Link2Me

,