'2018/05'에 해당되는 글 9건

etc

초대장 줌.


덧글 or 방명록


이메일 기재 필수.

'etc' 카테고리의 다른 글

5월 초대장 드림 [마감]  (42) 2018.05.29
와우프레스 네이버 공식블로그 선정기념 이벤트  (0) 2018.05.21
뮤지컬<파워레인저>  (0) 2018.05.15
4월 초대장 드림[마감]  (46) 2018.05.02
뮤지컬 <명성황후>  (0) 2018.04.12
뮤지컬 <캐리와 장난감 친구들>  (0) 2018.04.12
Programming/.NET

System.DateTime를 이용해 시간을 생성하는 방법은 다음과 같습니다.

 

DateTime dt = new DateTime(2015, 01, 01);

 

현재 시간을 알려면 Now 속성을 사용합니다.

 

Console.WriteLine(DateTime.Now.ToString());

 

UtcNow 속성은 UTC기준 현재 시간을 의미합니다.

 

Console.WriteLine(DateTime.UtcNow.ToString());

 

UTC(Universal Time, Coordinated)는 협정세계시로서 GMT(Greenwich Mean Time)라는 그리니치 평균시와 함께 세계 표준시로 사용되고 있습니다. UTC는 영국 그리니치 천문대가 있는 위치의 0도를 0시기준으로 하고 동쪽지역 분기선 이내에는 시간이 증가하고 서쪽으로는 시간이 감소하는 형태를 이루고 있습니다. 따라서 동쪽 분기선 안에 있는 대한민국은 +9시간을 해야하고 이시간이 한국 표준시(KST : Korea Standard Time)가 됩니다.

 

시간을 임의로 더하거나 빼고싶다면 AddMonths, AddDays등의 메서드를 이용할 수 있습니다.

 

DateTime plusMonth = DateTime.Now.AddDays(1);
DateTime minusHour = DateTime.Now.AddHours(-1);

 

이때 양수는 그만큼의 시간을 더하고 음수는 그만큼의 시간을 감소시킵니다. 이것 외에도 DateTime끼리 연산하는 경우도 있으나 이때는 사칙연산중 -만 허용하며 결과값은 TimeSpan으로 받아야 합니다.

 

DateTime now = DateTime.Now;
DateTime plusMonth = DateTime.Now.AddMonths(-1);

TimeSpan ts = now - plusMonth;

 

좀더 세밀한 시간을 알고자 한다면 Ticks속성을 사용할 수 있습니다. Ticks는 1년 1월 1일 12시부터 지금까지 100나노초 간격으로 흐른시간을 나타냅니다.

 

Console.WriteLine(DateTime.Now.Ticks.ToString());

 

그런데 이 Ticks값은 유닉스계열이나 기타 다른 플렛폼에서 기준으로 하는 1970년 1월 1일과는 다르기 때문에 만약 이런 플렛폼들과 호환성을 맞추려 한다면 1970년만큼의 시간을 더해야합니다. 다행이 100나노초단위는 같으므로 다음과 같이 처리할 수 있습니다.

 

Console.WriteLine(((DateTime.UtcNow.Ticks - 621355968000000000) / 1000).ToString());

 

 

'Programming > .NET' 카테고리의 다른 글

[C#] Encoding / BitConverter  (0) 2018.06.19
[C#] fixed  (0) 2018.06.13
[C#] DateTime  (0) 2018.05.29
[C#] 생성자와 소멸자  (0) 2018.05.23
[C#] 개체의 생성과 해제  (0) 2018.05.15
[C#] 호출자 정보 (CallerMemberName / CallerFilePath / CallerLineNumber)  (0) 2018.05.08
0 0
Programming/.NET

클래스의 생성자는 클래스명과 같은 메서드를 정의함으로서 구현할 수 있습니다.

 

class MyClass
{
    public MyClass()
    {

    }
}

 

생성자는 말 그대로 클래스의 개체가 생성될때 호출되는 메서드입니다. 여기에 각종 변수의 초기화나 혹은 필요한 매개변수를 받아 클래스에서 사용되는 데이터를 초기화 하는 것이 가능합니다.

 

class MyClass
{
    public MyClass(int i, int j)
    {
        MyValue = i + j;
    }

    public int MyValue
    {
        get;
        set;
    }
}

 

예제에서 클래스는 개체생성시 두개의 매개변수를 받아 MyValue라는 속성값을 초기화 하도록 하였습니다.

 

static void Main(string[] args)
{
    MyClass m = new MyClass(10, 20);
    Console.WriteLine(m.MyValue);
}

 

소멸자는 GC에 의해 해당 개체의 자원을 해제할때 호출되는 메서드입니다. 이 메서드는 클래스이름앞에 ~문자만 붙이면 소멸자 메서드가 됩니다.

 

class MyClass
{
    public MyClass(int i, int j)
    {
        MyValue = i + j;
    }

    public int MyValue
    {
        get;
        set;
    }

    ~MyClass()
    {

    }
}

 

소멸자는 임의로 호출하는 것이 불가능하며 GC가 수행될때 호출됩니다. 소멸자는 그 특성으로 인해 소멸자에서 뭔가를 임의로 처리하는 경우는 거의 없습니다. 간혹 비관리메모리를 사용한 경우 GC에 의해 해제될 수 없기에 소멸자에서 명시적으로 해제에 필요한 코드를 담는 경우가 있기는 하지만 활용도가 크지는 않습니다.

 

class MyClass : IDisposable
{
    IntPtr myMemory;

    public MyClass()
    {
        myMemory = Marshal.AllocCoTaskMem(1024);
    }

    public void Dispose()
    {
        Marshal.FreeCoTaskMem(myMemory);
    }

    ~MyClass()
    {
        Dispose();
    }
}

 

소멸자가 있는 클래스에 new로 개체를 생성하면 이 개체를 힙에 저장하고 동시에 '종료큐'라고 하는 곳에도 개체를 등록하게 됩니다. GC가 이 개체를 힙에서 제거하고자 할때 종료큐에 들어간 개체를 Freachable에 옮기게 되면 CLR에 의해 생성된 스레드가 Freachable안에 존재하는 개체의 소멸자를 호출한뒤 Freachable안에서 개체를 제거하게 됩니다. 그리고 힙에 존재하는 개체는 GC가 실행될때 비로소 힙에서 제거됩니다. 이 복잡한 과정때문에 소멸자가 존재하는 클래스는 GC에 부담스럽게 작용하고 때문에 꼭 필요하지 않다면 소멸자를 별도로 생성하는건 권장하지 않습니다.

 

하지만 만약 클래스의 Dispose() 메서드가 명시적으로 호출될 수 있는 상황이고 이때 GC가 소멸자를 다룰 필요가 없는 경우라면 Dispose() 메서드에서 GC의 SuppressFinalize() 메서드를 호출하여 종료큐에서 개체를 제거하도록 할 수 있습니다. 이렇게 되면 GC가 소멸자를 고려할 필요가 없으므로 GC의 부담을 줄여줄 수 있게 됩니다.

 

class MyClass : IDisposable
{
    IntPtr myMemory;

    public MyClass()
    {
        myMemory = Marshal.AllocCoTaskMem(1024);
    }

    public void Dispose()
    {
        objectRemove(true);
    }

    private void objectRemove(bool self_call)
    {
        Marshal.FreeCoTaskMem(myMemory);

        if (self_call)
            GC.SuppressFinalize(this);
    }

    ~MyClass()
    {
        objectRemove(false);
    }
}

'Programming > .NET' 카테고리의 다른 글

[C#] fixed  (0) 2018.06.13
[C#] DateTime  (0) 2018.05.29
[C#] 생성자와 소멸자  (0) 2018.05.23
[C#] 개체의 생성과 해제  (0) 2018.05.15
[C#] 호출자 정보 (CallerMemberName / CallerFilePath / CallerLineNumber)  (0) 2018.05.08
[C#] 람다식 (Lambda expression)  (0) 2018.05.02
0 0
etc


'etc' 카테고리의 다른 글

5월 초대장 드림 [마감]  (42) 2018.05.29
와우프레스 네이버 공식블로그 선정기념 이벤트  (0) 2018.05.21
뮤지컬<파워레인저>  (0) 2018.05.15
4월 초대장 드림[마감]  (46) 2018.05.02
뮤지컬 <명성황후>  (0) 2018.04.12
뮤지컬 <캐리와 장난감 친구들>  (0) 2018.04.12
0 0
etc


https://blog.naver.com/q_w963/221276046616

'etc' 카테고리의 다른 글

5월 초대장 드림 [마감]  (42) 2018.05.29
와우프레스 네이버 공식블로그 선정기념 이벤트  (0) 2018.05.21
뮤지컬<파워레인저>  (0) 2018.05.15
4월 초대장 드림[마감]  (46) 2018.05.02
뮤지컬 <명성황후>  (0) 2018.04.12
뮤지컬 <캐리와 장난감 친구들>  (0) 2018.04.12
0 0
Programming/.NET

C#에서 개체는 new로 할당될 수 있습니다.

 

static void Main(string[] args)
{
    MyClass m = new MyClass();
}

 

그런데 개체를 생성하고 난 후 해당 개체를 명시적으로 해제하고자 한다면 개체를 생성한 클래스에서 IDisposable 인터페이스를 상속해 해제에 필요한 Dispose()  메서드를 구현해야 합니다.

 

static void Main(string[] args)
{
    MyClass m = new MyClass();
    m.Dispose();
}

 

class MyClass : IDisposable
{
    public void Dispose()
    {
        this.Dispose();
    }
}

 

직접 구현한 클래스가 아닌 BCL의 다른 클래스라 하더라도 자원해제가 필요한 클래스는 IDisposable 인터페이스를 상속받고 있으므로 Dispose() 메서드를 호출할 수 있습니다. 그러나 Dispose()메서드를 호출하는 구문을 작성했어도 내부적으로 오류가 발생하면 해당 구문이 호출되지 않을 수도 있습니다.

 

static void Main(string[] args)
{
    MyClass m = null;

    try {
        m = new MyClass();
    } catch { } finally {
        m.Dispose();
    }
}

 

그래서 try ~ catch구문을 사용해 오류발생상황과는 상관없이 Dispose()를 호출할 수 있도록 해주거나

 

static void Main(string[] args)
{
    using (MyClass m = new MyClass()) {
        //
    }
}

 

아니면 using으로 감싸는 방법을 쓰는것이 좋습니다. using은 using영역이 끝나는 지점에서 개체의 Dispose() 메서드를 자동으로 호출합니다.

0 0
Programming/.NET

특정 메서드가 호출될때 해당 메서드는 호출하는 측의 정보를 확인할 수 있습니다.

 

static void myMethod(string s[CallerMemberName] string cmn = ""[CallerFilePath] string cfp = ""[CallerLineNumber] int cln = 0)
{
    Console.WriteLine(s + "호출자 메서드 이름 : {0} - 호출자 파일 경로 : {1} - 호출자 소스코드 라인번호 : {2}"cmncfpcln);
}

 

메서드에서 호출자의 정보를 확인할 수 있는건 예제에서 쓰인 단 3가지 뿐입니다. 메서드에서 매개변수형식을 이와 같이 정의해 놓으면 해당 매개변수에는 호출자 정보가 자동으로 들어가게 됩니다.

 

따라서 호출하는 쪽에서는 원래 호출하는 방식 그대로 메서드를 호출하면 됩니다.

 

myMethod("호출자 정보 => ");

0 0
Programming/.NET

람다식은 수학에서의 람다대수형식을 C#언어의 문법으로 표현한것입니다. 람다식을 사용하면 기존의 길고 복잡했던 구문을 간소화하고 단순화시킬 수 있습니다.

 

예를 들어 익명메서드를 사용한 하나의 예를

 

delegate int callMethod(int iint j);

static void Main(string[] args)
{
    callMethod cm = delegate (int iint b)
    {
        return i + b;
    };

    Console.Read();
}

 

람다식으로 표현하면 다음과 같이 할 수 있습니다.

 

delegate int callMethod(int iint j);

static void Main(string[] args)
{
    callMethod cm = (ib) => i + b;

    Console.Read();
}

 

우선 callMethod 타입에서는 델리게이트 선언으로 인해 델리게이트형식의 익명메서드, 그리고 해당 메서드에 int형 매개변수 2가 전달된다는 것을 알 수 있습니다. 따라서 deleteage와 int형식은 다음과 같이 생략할 수 있습니다.

 

delegate (int i, int b) -> (i, b)

 

그리고 이 생략된 표현이 람다식임을 => 문자로 알려줍니다.

 

람다식 표현에서 반환값이 없는 경우에는 중괄호({})가 있어야 하지만 반환값이 존재하는 경우에는 return과 해당 부분을 감싸는 중괄호가 생략될 수 있기에 최종적으로 다음과 같은 표현이 완성됩니다.

 

(i, b) => i + b;

 

callMethod cm = (ib) => i + b;
Console.WriteLine(cm(100, 200));

 

예제에서는 람다식으로 델리게이트를 사용해 익명 메서드를 구현하고 있습니다. 이것은 일반적인 익명 메서드도 마찬가지지만 람다식으로 익명 메서드를 구현하기 위해서는 일일이 델리게이트를 선언해야 한다는 것을 의미합니다. 이런 불편함을 감소시키고자 .NET에서는 델리게이트의 일부 형식을 구현한 Action과 Func를 마련해 두었습니다.

 

static void Main(string[] args)
{
    Action<int> a_i = (i) => { Console.WriteLine("number : {0}"i)};
    a_i(100);

    Console.Read();
}

 

먼저 Action은 반환값이 없는 익명메서드를 구현하는데 사용됩니다. Action에 보시면 매개변수로 받을 수 있는 데이터형식을 <int>로 정의했는데 이것은 Action<T>로 제네릭화 되어있다는 것을 알 수 있습니다. 이런 사항은 Func도 마찬가지입니다.

 

Func<intintint> cal = (ij) => i + j;
int sum = cal(100, 200);
Console.WriteLine(sum);

 

Func는 반환값이 있는 경우에 사용할 수 있습니다. 예제에서 Func는 매개변수 데이터 형식으로 int형 3개가 존재하는데 처음 2개는 i와 j에 대응되고 나머지 하나는 반환형식에 해당합니다.

 

Action과 Func사용시 매개변수는 최대 16개까지 유동적으로 사용할 수 있습니다.

 

람다식은 익명메서드를 구현하는것 뿐만 아니라 컬렉션에도 적용할 수 있습니다. 예를 들어

 

List<int> l = new List<int{ 1, 2, 3, 4, 5 };

 

위와 같은 List의 경우 각 요소를 순회하려면 다음과 같이 할 수 있지만

 

foreach (int i in l)
    Console.WriteLine(i);

 

Action 람다식을 적용하면

 

l.ForEach((el) => { Console.WriteLine(el)});

 

이와 같이 처리할 수 있습니다. 예제를 보면 컬렉션의 ForEach메서드를 사용하는데 이 메서드는 Action<T>타입을 받으므로 람다식의 Action을 전달하면 됩니다.  다음 예제는 ForEach의 또 다른 처리방식을 보여주고 있습니다.

 

Array.ForEach(l.ToArray()(el) => { Console.WriteLine(el)});

 

Action은 리턴값을 가지지 않는다고 하였습니다. 따라서 특정 조건에 해당하는 요소만을 반환받으려면 Func를 사용할 수 있습니다.

 

List<int> r = l.FindAll((el) => el > 3);
r.ForEach((el) => { Console.WriteLine(el)});

 

이때 메서드는 FindAll을 사용하며 Func를 구현하는 람다식을 통해 3보다 큰 값만 가져오도록 하였습니다. FindAll과 비슷한 메서드로 Where도 존재하는데

 

IEnumerable<int> r = l.Where((el) => el > 3);
Array.ForEach(r.ToArray()(el) => { Console.WriteLine(el)});

 

이때 Where는 List가 아닌 IEnumerable형식으로 결과를 반환합니다. IEnumerable은 자체적인 ForEach메서드를 지원하지 않으므로 Array의 ForEach를 호출해 결과요소를 반환받아야 합니다. 이때 만약 반환되는 데이터 타입을 달리해야 한다면 Select를 사용할 수 있습니다.

 

IEnumerable<double> r = l.Select((el) => double.Parse((el > 3).ToString()));

 

FindAll과 Where메서드는 결과는 같지만 동작방식은 약간 다른데 Where메서드는 호출되는 즉시 동작하지 않고 ForEach로 배열순회가 되서야 실행이 됩니다. 이를 지연된 평가라고 하는데 이때문에 요소를 임의적으로 정리만 해준다면 Where에서 다루어지는 요소가 전체가 아닌 일부만으로 처리될 수 있기에 성능적으로 도움이 될 수 있습니다.

 

위 예제에서 사용된 Select도 마찬가지인데 이는 ConvertAll에서 지연된 평가를 위해 만들어진 메서드입니다. 이처럼 람다식자체는 메서드나 컬렉션에서 특정 연산을 위해 사용될 수 있습니다.

 

이 외에도 람다식은 식자체를 데이터로서 취급하는 방법이 존재합니다. 예를 들어 Func에 관한 람다식을 데이터로 하려면

 

Expression<Func<intintint>> exp = (ij) => i + j;

 

위와 같이 할 수 있습니다. Expression<T>에서 T는 식에 해당하는 델리게이트타입이 전달되며 exp가 식을 담고 있는 변수에 해당합니다. 따라서 Expression 개체는 다음 형태처럼 구문에 대한 개별적인 표현이 가능합니다.

 

Expression<Func<intintint>> exp = (ij) => i + j;

BinaryExpression be = (BinaryExpression)exp.Body;
Console.WriteLine(be.ToString());

 

exp에서 Body는 식의 본체를 의미하고 이를 출력해 보면 (i + j)라는 내용을 확인할 수 있습니다. 그런데 반대의 경우도 가능해서 Expression을 통해 식을 구성할 수도 있습니다.

 

ParameterExpression Lpe = Expression.Parameter(typeof(int)"i");
ParameterExpression Rpe = Expression.Parameter(typeof(int)"j");

BinaryExpression plusBe = Expression.Add(Lpe, Rpe);

Expression<Func<intintint>> exp = Expression<Func<intintint>>.Lambda<Func<intintint>>(plusBe, new ParameterExpression[] { Lpe, Rpe });

 

좌항과 우항을 ParameterExprsssion으로 구성하고 BinaryExpression을 통해 2항 연산에 관한 식을 정의합니다. 이때 Expression의 Add 메서드를 통해 +연산자를 적용한뒤 연산자와 각항을 구성하고 Lamda메서드로 전체식을 구성합니다. 물론 BinaryExpression외에도 루프를 표현하는 LoopExpression이나 상수식을 표현하는 ConstantExpression등 구성할 수 있는 다양한 타입의 식이 존재합니다.

 

Console.WriteLine(exp.ToString());
Func<intintint> f = exp.Compile();
Console.WriteLine(f(10, 20));

 

위에서 처럼 식을 데이터로서 취급하면서도 컴파일과정을 통해 실제 실행가능한 코드로 동작시킬 수도 있습니다.

 

Expression<Func<intintint>> exp = (ij) => i + j;

Func<intintint> f = exp.Compile();
Console.WriteLine(f(10, 20));

 

식을 데이터로서 다루고자 하는 이러한 방법은 프로그램이 동작하는 시점에 필요한 처리로직을 동적으로 생성하고 실행할 수 있다는 것인데 사실 잘 쓰이지는 않는 방법입니다. 그냥 이런게 가능하다는 것만 알아두고 넘어가도 좋을듯 합니다.

 

참고로 람다식을 이용하면 익명메서드와 비슷하게 단일문의 메서드를 생성할 수 있습니다.

 

static void Main(string[] args)
{
    int sum = plus(10, 20);

    Console.Read();
}

static int plus(int iint j) => (i + j);

 

plus메서드는 2개의 매개변수값을 받아 하나의 결과를 반환하는 단일문으로 메서드가 구현되었습니다.

0 0
etc

빌어먹을... 초대장이면 초대장이지.. 뭔 한시적 초대장이여...?!


어쨌건 받았으니... 덧글 남기시면 드리오리다.





초대장배포 마감되었습니다.! 여러분의 뜨거운 성원에 힘입어 다음에도 티스토리가 같은 짓 반복했으면 합니다.

감사합니다.

1
블로그 이미지

클리엘