안녕하세요, 모스크바에 살고 있는 개발자 윤진입니다.


C로 개발을 할때는 헤더파일에 온갖 함수선언을 하며,

공동작업을 하는 개발자들끼리 전체적인 그림을 그리곤 했습니다.

그럴때마다 Java의 interface 기능이 무척이나 부러웠죠. :)


C#에서는 다양한 방법으로 모듈을 설계&구현할 수 있습니다.

- interface

- abstract class

- partial class

- virtual method


그렇지만, 각각이 목적과 쓰임이 다릅니다.

interface는 1) 메소드, 2) 속성, 3) 인덱서, 4) 이벤트 만을 사전에 선언하여,

해당 interface를 상속받는 class가 빈 껍데기를 구현하도록 유도하고 있습니다.

만약 아래 코드처럼 interface에 필드를 넣으면, 컴파일 에러가 발생합니다.

컴파일러 : "인터페이스는 필드를 포함할 수 없습니다"

    interface InterfaceWithVariable
    {
        string s; // Error
        int InterfaceMethod();
    }

변수가 있다는 것은 특정 상태를 기억한다는 것이기에,

이런 '상태'라는 것은 구현영역에서 처리하는게 맞습니다.


abstract class는 abstract 타입의 1) 메소드, 2) 속성, 3) 인덱서, 4) 이벤트가 하나 이상 포함된 class 입니다.

추가 구현이 필요한 abstract 타입 있다는 것 외에는 일반 class 정의하듯 만들면 됩니다.

그렇기에 필드에 대한 별도의 제약사항은 없습니다.

    abstract class AbstractWithVariable
    {
        int i;
        protected abstract int AbstractMethod(int argument);
    }

위의 예처럼 얼마든지 class 필드를 만들 수 있습니다.


partial class도 abstract class처럼 필드에 대한 제약이 없습니다.

일반 class를 복수개로 쪼개놓은 것이기 때문에, 분리된 것을 합치면 일반 class가 됩니다.

한 partial class에서 정의한 변수를 다른 다른 partial class에서 사용할 수 있습니다.

    partial class PartialWithVariable
    {
        int i = 10;
    }

    partial class PartialWithVariable
    {
        public void Print()
        {
            Console.WriteLine(i);
        }
    }


virtual method는 상속과정에서 부모-자식 간에 메소드 처리방식을 규정하기 때문에,

abstract나 partial처럼 변수에 대한 제약이 없습니다.

    public class VirtualClass
    {
        int i;
        public virtual void Print(int i)
        {
            Console.WriteLine(i);
        }
    }


이상으로 필드에 얽힌 간단한 이야기를 마치겠습니다.

끝_


안녕하세요, 요즘 도통 개발을 하지 않는 개발자 윤진입니다.


C#의 속성과 관련된 부분을 보다가 간단히 코드로 확인하고 싶은 바가 있어 남깁니다.



namespace ConsoleApplication2
{
    class Program
    {
        class Man
        {
            private int age;
            public string Name { get; set; }
            public int Age
            {
                get { return age; }
                set
                {
                    if (value > 10) age = 10;
                }
            }
        }

        static void Main(string[] args)
        {
            Man man = new Man();

            man.Name = "Jin";
            man.Age = 2;

            Console.WriteLine(man.Name + " : " + man.Age);
        }
    }
}


- 속성과 짝이 되는 변수를 반드시 적어줄 필요는 없습니다.

  다시 말하면, public string Name { get; set; }의 경우,

  컴파일러가 컴파일 시점에 private 변수를 만들어 위의 속성을 관리한다는 것이죠.

public class Man {
   public string Name { get; set; }
   public int age { get; set; }
}

위의 코드는 아래의 코드와 기능적으로 동일합니다.

public class Man {
private string name; private int age; public string Name { get { return name; } set { name = value; } } public int Age { get { return age; } set { age = value; } } }


- 빈 getter / setter 지정

  속성을 { get; set; }으로 지정하면,

  별도의 루틴없이 get / set이 되므로, 외부에서 봤을때는 속성이 변수처럼 동작합니다.


- 동시에 정의해야 하는 getter / setter

  get {} 을 정의했다면, set {}도 정의해야합니다.

  만약 get만 정의하고 set을 정의하지 않으면, 컴파일 에러가 뜹니다.

  정의를 하려면 양쪽 모두에 사이좋게 정의해주세요.


- 키워드 value

  set 루틴에서, 사용자가 입력한 값을 value라는 키워드라 지칭합니다.

  if (value > 10)과 같은 루틴으로 value를 건네받아 사용할 수 있습니다.


이상으로 간단한 속성의 성질을 알아보았습니다.

_끝



안녕하세요, 모스크바에서 생활하고 있는 개발자 윤진입니다.

벌써 2월이 넘었네요.

이제 3월이면 한국으로 귀국합니다. 우훗.


윈도우 프로그래밍을 하려고 이곳저곳 기웃거리며 귀동냥을 하다가,

Modal과 Modeless의 작명 이유에 대해 쓰여진 글을 발견하였습니다.

예전부터 왜 저런식으로 작명했는지 궁금했었는데 오늘에서야 드디어 답을 얻었습니다.


With a modal dialog, you set your application in a particular mode (a different "state" if you will), whereby only actions pertaining to that "mode" are accepted, hence preventing UI actions outside of the dialog.


At Andreas' prompting I thought I may have to dig dusty Windows API books, as often, the etymology/origin of a word or expression that has became broadly accepted is only found in early documentation, but in fact we still see this referenced in an online glossary from MS. The Modal entry reads (emphasis is mine):

modal

Restrictive or limited interaction due to operating in a mode. Modal often describes a secondary window that restricts a user's interaction with the owner window. See also: modeless.



Modal에서는 새로운 뷰가 열렸을 때 기존의 뷰를 사용할 수 없습니다.

이 경우 뷰를 관리하는 앱 입장에서는 새로운 상태(곧, 모드)에 진입한 셈이고,

새로운 뷰로만 이벤트를 건네주고 이전 뷰로는 이벤트가 넘어가지 않습니다.


Modeless는 새로운 뷰가 열린다고 하여 새로운 모드에 진입하는 것은 아닙니다.

기존 뷰와 새로운 뷰 각각이 이벤트를 받을 수 있습니다.

그렇기에 별도의 모드가 없다고 하여 모달리스라 명명된 것입니다.



* 출처

http://stackoverflow.com/questions/1607783/why-is-a-modal-modeless-dialog-called-modal-modeless




안녕하세요,

이번에는 아주 간단한 사실 하나만 확인하고 넘어가겠습니다.


소수점이 있는 숫자 뒤에 'f'(float0나 'd'(double)를 붙이지 않으면,

해당 숫자는 어떤 타입이 될까요?

정답은 C나 C++과 마찬가지로 double 타입입니다.



    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine((3.14).GetType());
        }
    }


위의 코드를 실행하면,

"System.Double"이라는 결과가 나옵니다.


그렇다면, float 변수에 아무 suffix가 없는 숫자를 넘기면 어떻게 될까요?



    class Program
    {
        static void Main(string[] args)
        {
            float f = 3.14;
            Console.WriteLine(f);
        }
    }


위의 코드를 실행하면 컴파일 에러가 발생합니다.

"double 형식의 리터럴을 암시적으로 'float' 형식으로 변환할 수 없습니다. 이 형식의 리터럴을 만들려면 'F' 접미사를 사용하세요."

위의 오류 메시지에서 제안한대로 숫자 뒤에 F를 붙이고 다시 컴파일 해보겠습니다.



    class Program
    {
        static void Main(string[] args)
        {
            float f = 3.14F;
            Console.WriteLine(f);
        }
    }


위의 코드는 정상적으로 컴파일이 되고,

콘솔에 3.14가 찍힙니다.


이상 간단한 사실을 확인해보았습니다.



안녕하세요,

모스크바에서 개발과 담을 쌓고 살고 있는 개발자 윤진입니다.


C#에는 readonly라는 직설적인 이름의 키워드가 있습니다.

변수를 상수로 만들어버려, 변수값을 바꿀 수 없게 만드는 const와 유사해보이기도 하는데요.


readonly는 const와는 다르게 compile 시점에 값을 확정하지 않습니다.

반면, const는 소스코드에 명시된 변수값을 compile 시점에 확정하지요.


readonly는 프로그램이 메모리에 올라가는 runtime 시점에 이르러서야 값을 확정할 수 있습니다.

다음 두 경우에만 변수를 초기화할 수 있고 이후에는 갱신할 수 없습니다.


1) 변수를 선언하는 경우

2) 생성자 안에서 변수값을 바꾸는 경우


기기가 부팅하면서부터 함께 초기화되는 풀 스크린 UI 의 경우,

디스플레이의 해상도에 따라 화면구성요소의 크기가 달라질 수 있습니다.

앱은 런타임 중 최초 한 번에 한해 해상도를 확정짓고, 해상도에 맞게 구성물의 크기를 설정해둡니다.

이렇게 확정된 값은 프로세스가 종료되기 전까지 계속 사용할 수 있습니다.


물론, 위의 간단한 예시는,

기기가 한 번 부팅된 이후에는 해상도가 변하지 않는다는 것을 전제로 하고 있습니다.

환경설정에서 언제든 해상도를 바꿀 수 있는 디바이스에서는,

위와 같은 경우에 readonly 변수는 사용해서는 안됩니다. :(


플랫폼은 다양한 기기에 올라갈 수 있기 때문에,

여러 디바이스에서 유연하게 동작하도록 준비해야합니다.

기기마다 달라지는 요소(ex. 해상도)는 부팅 중에 메모리 영역에 데이터 조각으로 저장되고,

프로세스에서는 해당 데이터를 가지고 와서 readonly 변수에 저장해두고 두고두고 참조할 수 있습니다.


readonly는 (정의에 제한이 있지만) 일반 변수처럼 런타임 중에 값을 설정할 수 있기 때문에,

compile 중에 처리되는 const와 같은 성능 상의 이점은 없습니다.

그렇기 때문에 const를 사용할 수 있는 곳이라면 const를 사용하는 것이 조금 더 성능에 기여할 수 있습니다.


오늘은 이것으로 마치겠습니다.


안녕하세요,

러시아에서 생활하고 있는 개발자 윤진입니다.


C#에는 정말 흥미로운 기능들이 많이 있더군요.

한국에서 공수해온 C# 책에서는 기능에 대한 단편적인 설명만 있어서,

해당 기능에 대한 존재의미(레종데트르)를 고민하게끔 만들어주는데요.


이번에는 partial class에 대해 간단히 탐구해보도록 하겠습니다.

partial class는 class를 정의할때 한군데가 아닌,

복수의 장소에서 class를 정의할 수 있도록 지원하고 있습니다.



partial class Korea
{
    public int south;
}

partial class Korea
{
    protected int north;
}


- Code Generator 자동생성

윈도우 폼을 생성할 때,

Code generator는 partial class를 Form1.cs과 Form1.Designer.cs 파일에 나눠 정의됩니다.

Code generator는 클래스 내부에서 개발자가 손 댈 필요가 없는 부분을 떼어 Form1.Designer.cs에 놓고,

개발자의 손길을 거쳐야하는 부분만 Form1.cs에 놓아, 개발자가 필요한 코드에만 집중하도록 지원합니다.


- 다수 개발자의 개발

다수의 개발자가 한 클래스를 개발하는 경우를 상상해보면,

개발자들은 단위기능으로 적당히 역할분담을 할 것입니다.

이 경우 partial class를 사용하여 여러 파일에서 개발하면,

한 파일에서 작업할 때 발생할 수 있는 conflict를 막을 수 있습니다.


- partial method 사용

다수의 개발자가 한 클래스를 개발할 때,

partial class의 한 부분에서는 함수선언만 하고, 다른 부분에서는 함수정의를 할 수 있습니다.

partial class의 한 부분이 추상클래스이고, 다른 부분이 구현 클래스가 되겠네요.

만약, partial method가 정의되지 않았다면,

컴파일 이전에 선언된 method를 제외하고 컴파일을 하게 됩니다.


단, partial method는 아래의 세가지 조건을 만족해야 합니다.

1. 선언과 정의의 타입이 일치해야합니다.

이는 따로 고민할 필요도 없는 당연한 이야기입니다.


2. 메소드는 반드시 void를 리턴해야합니다.

partial은 선언과 구현을 분리하여 진행할 수 있으므로,

특정 컴파일 시점에서는 선언만 되어 있을 수 있습니다.

만약 partial method의 return 값이 void 외의 타입이라면,

해당 return 값을 특정 변수에 넣을 수 있겠죠.

그렇지만, partial method가 정의되지 않은 상태이기 때문에,

해당 변수는 제대로 초기화 혹은 정의될 수 없습니다.

이런 잠재적인 문제를 막기위해 partial은 void를 리턴하도록 하고 있습니다.


3. 접근 수준은 오직 partial로 이는 private입니다.

이는 컴파일 시점에 partial method가 구현되어 있지 않으면,

컴파일러가 컴파일 대상에서 빼버리는 것과 관련있습니다.

선언만 되어 있는 partial method를 class 외부에서 사용하고 있다면,

컴파일 시점에 해당 메소드를 참조할 수 없어 제대로 컴파일 되지 않겠죠.

이 문제를 해소하려면, 

1) partial method를 정의하거나 2) 외부에서 사용하는 부분을 제거해야 하죠.

그렇지만, 이는 일반 method의 사용양식과 별반 다를게 없죠.

partial method는 선언만 되어있는 상태라 해도 무결하게 컴파일되는 상태이니까요.


MSDN에서 예시로 든 코드를 보면, 위의 조건을 확인할 수 있습니다.


    namespace PM
    {
        partial class A
        {
            partial void OnSomethingHappened(string s);
        }

        // This part can be in a separate file.
        partial class A
        {
            // Comment out this method and the program
            // will still compile.
            partial void OnSomethingHappened(String s)
            {
                Console.WriteLine("Something happened: {0}", s);
            }
        }
    }


다른 유용한 경우도 있을 수 있습니다.

추가로 발견하면 갱신하도록 하겠습니다.


즐거운 하루 보내세요~



* Reference

https://msdn.microsoft.com/en-us/library/6b0scde8.aspx


  1. Cargold 2019.01.25 14:07

    1인 개발하는 상황이지만 스크립트를 분할해서 봐야하는 상황이 생겨서 파티셜 키워드를 써보려고 하는데요.
    정리하신 내용이 좋네요. 감사합니다.



안녕하세요,

밤마다 이어지는 모스크바의 눈발 때문에-

퇴근길이 험난하기만한 개발자 윤진입니다.


C#의 문자열을 살펴보다가 의문이 들어 포스팅을 시작하려 합니다. :)


C에서 포인터로 들어간 문자열(문자들 + '\0')을 관리하였습니다만,

char *s = "string";

C#에는 포인터 대신 string class로 문자열을 관리하고 있습니다.

string s = "string";


이 사실을 접하자마자 처음 든 의문은,

C#에서 char[]을 string처럼 사용할 수 있는지 여부였습니다.


char[]와 string은 모두 다수의 문자를 저장할 수 있지만,

char는 struct, string은 class인 만큼 둘 사이에 간극은 큽니다.

그렇기 때문에 char[]는 string이라고 말할 수 없고,

char[]가 string이 되기 위에서는 배열을 문자열로 변환해주는 생성자나 메소드를 이용해야 합니다.


- 생성자를 이용하여 char[]를 string으로 변환하기

char[] characters = {'s', 't', 'r', 'i', 'n', 'g'};
string str = new string(characters);


- 메소드를 이용하여 char[]를 string으로 변환하기

char[] characters = {'s', 't', 'r', 'i', 'n', 'g'};
string str = string.Join("", characters);

char[] characters = {'s', 't', 'r', 'i', 'n', 'g'};
string str = string.Concat(character);


char[]를 콘솔로 출력할 때는 Console.Write() 메소드에 char[]를 넣으면 됩니다.

Console.Write()는 string 뿐만 아니라 char[]도 아규먼트로 받고 있죠.

[C#]
public static void Write(
 char[] buffer
);


string은 그 밖에 흥미로운 특징이 많으므로 따로 한 번 더 살펴볼까 합니다.


그럼 좋은 하루 보내세요.






안녕하세요,

러시아 모스크바에서 생활하고 있는 개발자 윤진입니다.

영하 24도로 시작하는 상쾌한 아침이라 외출하기가 너무 겁나네요.

그래서 이렇게 두문불출하고 있습니다. 우훗.


이번에는 모든 프로그래밍 언어의 기본이라 할 수 있는 자료형변환에 대해 살짝 살펴보겠습니다.

C언어에서는 0, 1 값을 false, true로 매핑하여 사용했는데요,

(물론, stdbool.h를 불러와서 사용할 수도 있었죠.)

C#에도 아래 코드처럼 int를 boolean으로 바꿀 수 있지 않을까 기대했었죠.

Console.WriteLine(Boolean.Parse(1));

하지만, 위의 코드는 동작하지 않더군요. :)


C#에서는 boolean structure를 사용해서 false, true 값을 지정할 수 있습니다.

[SerializableAttribute]
[ComVisibleAttribute(true)]
public struct Boolean : IComparable, IConvertible, IComparable, 
	IEquatable


그렇다면, Parse()도 어떤 type의 값을 argument로 받아 들일까요?

MSDN을 뒤져보니 Parse() 메소드는 스트링 값만 받아들이고 있었습니다.

C에 익숙하기 때문에 Parse(0) 이나 Parse(1) 같은 형태로 사용할 수 없는게 내심 아쉽더군요.

Parse(String)

Converts the specified string representation of a logical value to its Boolean equivalent.



하지만, Convert.ToBoolean() 메소드를 통해 온갖 byte, int, char, string 등의 값을 boolean으로 바꿀 수 있습니다.

            Console.WriteLine(Convert.ToBoolean(0)); // False
            Console.WriteLine(Convert.ToBoolean(1)); // True

StackOverFlow에 걸린 답변들을 보니,

Convert.ToBoolean()는 다양한 형을 argument로 받아 bool.Parse() 보다 느릴 수도 있다는 의견도 있습니다만,

bool.Parse(string)과 Convert.ToBoolean(string)을 비교해보면,

결국 같은 루틴에 유사한 성능을 보일거라 생각합니다.


Overload List

NameDescription
System_CAPS_pubmethodSystem_CAPS_staticToBoolean(Boolean)

Returns the specified Boolean value; no actual conversion is performed.

System_CAPS_pubmethodSystem_CAPS_staticToBoolean(Byte)

Converts the value of the specified 8-bit unsigned integer to an equivalent Boolean value.

System_CAPS_pubmethodSystem_CAPS_staticToBoolean(Char)

Calling this method always throws InvalidCastException.

System_CAPS_pubmethodSystem_CAPS_staticToBoolean(DateTime)

Calling this method always throws InvalidCastException.

System_CAPS_pubmethodSystem_CAPS_staticToBoolean(Decimal)

Converts the value of the specified decimal number to an equivalent Boolean value.

System_CAPS_pubmethodSystem_CAPS_staticToBoolean(Double)

Converts the value of the specified double-precision floating-point number to an equivalent Boolean value.

System_CAPS_pubmethodSystem_CAPS_staticToBoolean(Int16)

Converts the value of the specified 16-bit signed integer to an equivalent Boolean value.

System_CAPS_pubmethodSystem_CAPS_staticToBoolean(Int32)

Converts the value of the specified 32-bit signed integer to an equivalent Boolean value.

System_CAPS_pubmethodSystem_CAPS_staticToBoolean(Int64)

Converts the value of the specified 64-bit signed integer to an equivalent Boolean value.

System_CAPS_pubmethodSystem_CAPS_staticToBoolean(Object)

Converts the value of a specified object to an equivalent Boolean value.

System_CAPS_pubmethodSystem_CAPS_staticToBoolean(Object, IFormatProvider)

Converts the value of the specified object to an equivalent Boolean value, using the specified culture-specific formatting information.

System_CAPS_pubmethodSystem_CAPS_staticToBoolean(SByte)

Converts the value of the specified 8-bit signed integer to an equivalent Boolean value.

System_CAPS_pubmethodSystem_CAPS_staticToBoolean(Single)

Converts the value of the specified single-precision floating-point number to an equivalent Boolean value.

System_CAPS_pubmethodSystem_CAPS_staticToBoolean(String)

Converts the specified string representation of a logical value to its Boolean equivalent.

System_CAPS_pubmethodSystem_CAPS_staticToBoolean(String, IFormatProvider)

Converts the specified string representation of a logical value to its Boolean equivalent, using the specified culture-specific formatting information.

System_CAPS_pubmethodSystem_CAPS_staticToBoolean(UInt16)

Converts the value of the specified 16-bit unsigned integer to an equivalent Boolean value.

System_CAPS_pubmethodSystem_CAPS_staticToBoolean(UInt32)

Converts the value of the specified 32-bit unsigned integer to an equivalent Boolean value.

System_CAPS_pubmethodSystem_CAPS_staticToBoolean(UInt64)

Converts the value of the specified 64-bit unsigned integer to an equivalent Boolean value.



* Reference

https://msdn.microsoft.com/en-us/library/system.boolean(v=vs.110).aspx




안녕하세요,

러시아에서 아주 가끔 코딩을 하는 개발자 윤진입니다.


유니코드를 뒤적뒤적 살펴보다가,

유니코드에 한글이 어떻게 매핑되어 있는지 궁금해졌습니다.


유니코드에 매핑된 문자를 확인하고 싶으면 유니코드 공식홈페이지를 찾으면 됩니다.

공식 홈페이지에 올라와있는 Unicode 9.0 Character Code Charts에는,

한글 자소와 완성형 한글이 45장에 걸쳐 빽빽하게 기록된 것을 볼 수 있습니다.


한글자소는 초성/중성/종성으로 나눠져 세 그룹으로 표현되어 있습니다.

현대 한글에서 사용하는 초성은,

'ㄱㄲㄴㄷㄸㄹㅁㅂㅃㅅㅆㅇㅈㅉㅊㅋㅌㅍㅎ'로 총 19자입니다.

그렇지만, 한글자소 테이블에는 위의 한글 외에도 기이한 형태의 자음이 복합된 초성이 포함되어 있습니다.

'ㅎ'에 이어서 'ㄴㄱ'이나 'ㄴㄴ', 'ㄴㄷ', 'ㄴㅂ'이 연이어 초성으로 등장하는데요.

어떻게 읽으면 좋을지 감도 떠오르지 않는 문자들이 이어집니다.

무언가 규칙이 있는 것으로 보이는데 쉽게 읽히지는 않습니다.


중성도 한국의 사전순서를 따르고 있습니다.

'ㅏㅐㅑㅒㅓㅔㅕㅖㅗㅘㅙㅚㅛㅜㅝㅞㅟㅠㅡㅢㅣ' 총 21자의 모음이 등장합니다.

그리고 초성과 마찬가지로 가지각색의 이중모음이 뒤따르고 있습니다.


종성도 실제 사용하는 한글부터 등장합니다.

'ㄱㄲㄳㄴㄵㄶㄷㄹㄺㄻㄼㄽㄾㄿㅀㅁㅂㅄㅅㅆㅇㅈㅊㅋㅌㅍㅎ' 총 27자의 받침이 나오고,

사용하지 않는 복합자음이 연이어 나옵니다.

초성과 중성까지 쓰여진 문자에는 종성이 붙지 않거나 27가지 중 한가지 받침이 붙을 수 있습니다.

곧, 종성에는 28가지 경우의 수가 나오게 됩니다.


따라서 완성형 한글을 모두 테이블에 기입하기 위해서는,

초성자음 19자 * 중성모음 21자 * 종성자음(무받침 포함) 28 = 11,172글자

16*16 사이즈의 테이블에는 총 256글자가 들어가니,

11,172글자를 모두 테이블에 담기 위해서는 16*16 테이블 44개가 필요합니다.


물론 11,172글자 중에는 실제로 사용되지 않는 글자도 많이 있습니다.

'퐓, 풺, 햤' 이런 글자는 평소에 구경해본 적도 없습니다.

그렇지만, 유니코드는 사용여부가 아니라, 그저 조합 가능한 모든 경우를 따져 한글코드를 배치하였습니다.

그렇기 때문에 초성/중성/종성 자소만 가지고 완성형 글자의 위치를 쉽게 파악할 수 있습니다.


한글시작위치는 U+AC00로 여기에는 '가'가 매핑되어 있습니다.

그리고 '각갂갃간...' 등 총 28가지의 종성 경우의 수를 지나 29번째에 '개'가 나옵니다.

다시 28개를 지나면 '갸'가 등장합니다.

중성은 총 21개이기 때문에, 'ㄱ'이란 초성이 들어가는 글자는 21 * 28 = 588글자입니다.


'가'가 첫번째에 등장했다면,

'나'는 589번째에 등장하고,

'다'는 1177번째에 등장합니다.

이런 논리라면 한글자모만으로 완성형 글자의 위치를 얻거나

역으로 완성형 코드를 보고 어떤 자모인지 찾을 수 있습니다.



한글_베이스 U+AC00
중성_경우의_수 21
종성_경우의_수 28

함수 자소합치기(초성, 중성, 종성)
{
	완성형글자 = 한글베이스 +
		(초성 * 중성_경우의_수 * 종성_경우의_수) +
		(중성 * 종성_경우의 수) + 종성;
}

함수 자소나누기(완성형글자)
{
	초성 = (완성형글자 - 한글_베이스) /
		(중성_경우의_수 * 종성_경우의_수);

	중성 = (완성형글자 - 한글_베이스) %
		(중성_경우의_수 * 종성_경우의_수) / 종성_경우의_수;

	종성 = (완성형글자 - 한글_베이스) %
		종성_경우의_수;
}


원리를 명확하게 파악하기 위해,

위와 같이 코드를 풀어썼는데 반복되는 루틴이 많으니 실제로 코드에 옮길때는 최적화가 필요하겠네요.


그럼 오늘은 여기서 줄입니다.

좋은 하루 보내세요.

안녕하세요, 개발자 윤진입니다.


'17년 1월초 러시아에 파견나와 아침을 먹으며 C# 책을 뒤적거리다가 문득 궁금한게 생겼습니다.

'int.MaxValue'에 적용된 코딩컨벤션을 보면,

'int'는 class 혹은 struct로 보이지만, 첫글자가 소문자인 camelCase가 적용되어 있고,

MaxValue는 멤버변수이지만 첫글자가 대문자인 PascalCase가 적용되어 있는데요.


책에서 읽은 바에 따르면, 

- class & struct는 PascalCase를 따르고,

- 멤버변수는 camelCase를 따르게 되어 있습니다.


C#으로 된 남의 코드를 읽어본 경험이 전무하기 때문에,

책에 명시된 내용과 사뭇 다른 코드를 보니,

책에서 제대로 혹은 충분히 설명하지 않았을 것이란 생각이 들었습니다.


그래서, 약간의 검색을 하니 답은 굉장히 명쾌하더군요.


1. 'int.MaxValue'에서 'int'는 왜 camelCase를 사용할까요?

사실, int는 Int32 struct의 alias입니다.

alias가 개발자 편의나 코드 유지보수 위해 사용되고 있는 만큼,

int도 위와 같은 이유로 Int32를 alias하였습니다.

alias한 int가 마음에 들지 않는다면, 'Int32.MaxValue'와 같은 형태로 사용해도 되겠죠.


2. 'int.MaxValue'에서 'MaxValue'는 왜 PascalCase를 사용할까요?

이 부분은 마이크로소프트 코딩컨벤션 페이지를 보면 명확해집니다.


IdentifierCaseExample
ClassPascalAppDomain
Enum typePascalErrorLevel
Enum valuesPascalFatalError
EventPascalValueChange
Exception classPascalWebException
Note   Always ends with the suffix Exception.
Read-only Static fieldPascalRedValue
InterfacePascalIDisposable
Note   Always begins with the prefix I.
MethodPascalToString
NamespacePascalSystem.Drawing
ParameterCameltypeName
PropertyPascalBackColor
Protected instance fieldCamelredValue
Note   Rarely used. A property is preferable to using a protected instance field.
Public instance fieldPascalRedValue
Note   Rarely used. A property is preferable to using a public instance field.

출처 : "Capitalization Styles"


MaxValue는 Struct 내에 위치하며 외부에서 접근 가능한 변수입니다.

그렇기 때문에, Public instance field를 위한 코딩컨벤션을 따라주어야 하지요.

그래서 'int.MaxValue'라는 형태가 완성되었죠.


간단한 의문을 간단하게 해결해보았습니다.

그럼 즐거운 하루 보내세요.


+ Recent posts