2017년 3월 29일 수요일

C# 코딩의 기술 기본편 : 똑똑하게 코딩하는 법
가와마타 아키라 저/김완섭 역 | 길벗

http://m.yes24.com/Goods/Detail/20312268

C#을 쓰기 시작해서 책들을 찾아서 보고 있음.
좀 간단하게 볼만 한 책 중에서는 이 책이 있었음.

두권으로 구성되어 있고 그 중 실전편은 난 별로였으나 기본편은 C# 초보자에게는 간단하게 읽어 볼만 한 것 같다.

저자가 일본 사람이라서 그런지 꼼꼼하게 챕터가 정해진 것 같고 사소하지만 놓치기 쉬운 부분도 함께 정리한 듯 하다. 하지만 책이 대화로 구성되어서 난 보기 쉽지 않더라..

챕터 중 몰랐거나 볼만한 것들은 다음과 같고 나중을 위해 정리해둠.


1.6 루프할 필요가 없는 루프
1.8 해제되지 않는 참조
1.9 해제했다고 생각한 메모리
1.18 using문을 사용하지 않는 증후군

2.1 구세대 컬렉션 사용
2.9 XElement를 Nullable〈T〉로 변환할 수 있을 때
2.13 자바여 편히 잠들라

3.1 GAC에 얽힌 오해
3.2 Ngen 의존 증후군

2017년 3월 27일 월요일

[Link] Xamarin MessagingCenter, publish/subscribe 기반으로 coupling 간단한 message 전달 방법

View model과 다른 component간에 message를 사용하여 연동될 수 있도록 하는 방법이고 message에 대해서 subscribe, publish 하여 사용하므로 coupling을 줄일 수 있다.


: https://developer.xamarin.com/guides/xamarin-forms/application-fundamentals/messaging-center/
 

Simple String Message

The simplest message contains just a string in the message parameter. A Subscribe method that listens for a simple string message is shown below - notice the generic type specifying the sender is expected to be of type MainPage. Any classes in the solution can subscribe to the message using this syntax:
MessagingCenter.Subscribe<MainPage> (this, "Hi", (sender) => {
    // do something whenever the "Hi" message is sent
});
In the MainPage class the following code sends the message. The this parameter is an instance of MainPage.
MessagingCenter.Send<MainPage> (this, "Hi");
The string doesn't change - it indicates the message type and is used for determining which subscribers to notify. This sort of message is used to indicate that some event occurred, such as "upload completed", where no further information is required.

하지만 뭐든지 남용하는 건 안될 것 같다.
다음은 MessagingCenter를 사용하지 않아도 될 부분들을 정리해 놓은 내용이다.

Misuses Of MessagingCenter
: https://xamarinhelp.com/common-misuse-messagingcenter/

2017년 3월 8일 수요일

2017년 2월 16일 목요일

C#에서의 RAII(Resource Acquisition Is Initialization) idiom 구현

C++에서는 file이나 DB의 resoruce leak 처리를 위해서
RAII idiom을 자주 사용하곤 했었는데,

http://en.cppreference.com/w/cpp/language/raii
https://en.wikipedia.org/wiki/Resource_acquisition_is_initialization

#include <mutex>
#include <iostream>
#include <string> 
#include <fstream>
#include <stdexcept>

void write_to_file (const std::string & message) {
    // mutex to protect file access (shared across threads)
    static std::mutex mutex;

    // lock mutex before accessing file
    std::lock_guard<std::mutex> lock(mutex);

    // try to open file
    std::ofstream file("example.txt");
    if (!file.is_open())
        throw std::runtime_error("unable to open file");
    
    // write message to file
    file << message << std::endl;
    
    // file will be closed 1st when leaving scope (regardless of exception)
    // mutex will be unlocked 2nd (from lock destructor) when leaving
    // scope (regardless of exception)
}

C#에서는 destructor 사용에 신중해져야 해서
찾아보니 다음과 같은 글들이 있어 링크함.


요약하면 
- IDisposable 인터페이스를 구현하고
- 객체를 항상 삭제하는 using 문을 이용하여 RAII 객체를 사용하라는 것


MSDN의 IDisposable 설명에서도 언급하고 있다.

IDisposable을 구현 하는 개체를 사용 하 여

앱이 IDisposable 인터페이스를 구현 하는 개체를 사용 하는 경우 개체의 IDisposable.Dispose 구현을 사용 하는 경우 해당 개체의 구현을 호출 해야 합니다. 프로그래밍 언어에 따라 두 가지 방법 중 하나에서이 수행할 수 있습니다.

  • 및 Visual Basic에서 C# using 문과 같은 언어 구문을 사용 합니다.

  • try/finally 블록에 IDisposable.Dispose 구현에 대 한 호출을 래핑합니다.




RAII (Resource Acquisition Is Initialization) C# Helper Classes 예제
https://www.codeproject.com/Articles/122129/RAII-Resource-Acquisition-Is-Initialization-C-Help

using (var objGuard = new RAIIGuard&lt;int>(
                  () =>objStack.Pop(),
                  (e)=>objStack.Push(e)))
{
    ...
    if (objGuard.Item != 0)
    {
        return;
    }   
    ...
    if (...)
    {
         throw new ...;
    }
    ...
}



// used for symmetric actions like login, logout
public sealed class RAIIGuard: IDisposable
{
    private Action Cleanup { get; set; }
    public RAIIGuard(Action init, Action cleanup)
    {
        Cleanup = cleanup;
        if (init != null) init();
    }
    void IDisposable.Dispose() { if (Cleanup != null) Cleanup(); }
]
// used for symmetric actions that must pass
// over an object from init to cleanup and that
// need to provide the item to the "using" body
public sealed class RAIIGuard&lt;T>: IDisposable
{
    private Action&lt;T> Cleanup { get; set; }
    public T Item { get; private set; }
    public RAIIGuard(Func&lt;T> init, Action&lt;T> cleanup)
    {
        Cleanup = cleanup;
        Item = (init != null) ? init() : default(T);
    }
    void IDisposable.Dispose() { if (Cleanup != null) Cleanup(Item); }
]



Resource Acquisition is Initialization in C#
http://geekswithblogs.net/codeWithoutFear/archive/2012/06/28/raii-in-csharp.aspx

Here is a class and sample that combines a few features of C# to provide an RAII-like solution:

using System;

namespace RAII
{
    public class DisposableDelegate : IDisposable
    {
        private Action dispose;

        public DisposableDelegate(Action dispose)
        {
            if (dispose == null)
            {
                throw new ArgumentNullException("dispose");
            }

            this.dispose = dispose;
        }

        public void Dispose()
        {
            if (this.dispose != null)
            {
                Action d = this.dispose;
                this.dispose = null;
                d();
            }
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            Console.Out.WriteLine("Some resource allocated here.");

            using (new DisposableDelegate(() => Console.Out.WriteLine("Resource deallocated here.")))
            {
                Console.Out.WriteLine("Resource used here.");

                throw new InvalidOperationException("Test for resource leaks.");
            }
        }
    }
}

The output of this program is:

Some resource allocated here.
Resource used here.

Unhandled Exception: System.InvalidOperationException: Test for resource leaks.
   at RAII.Program.Main(String[] args) in c:\Dev\RAII\RAII\Program.cs:line 40
Resource deallocated here.







2017년 2월 15일 수요일

64bit architecture에서의 char* pointer byte size

C#에서 C 기반의 library에서 char**을 가져오려고
계속 시도하는데 죽는 현상이 발생해서 삽질을 하고 있었음.

Interop with Native Libraries: http://www.mono-project.com/docs/advanced/pinvoke/

: https://bytes.com/topic/c-sharp/answers/554501-c-c-interop-returning-char

계속 전달되는 char**의 IntPtr에서 char*를 읽기 위해 4bytes씩 읽어오도록 하고 있었는데..

정말 바보 같았다. malloc, memset에서도 sizeof를 그렇게 줄창 쓰면서도
왜!!! 바보같이 4bytes 읽어 왔었는지 급 한심스러워짐..

일단 MS에서도 아래와 같이 가이드를 주고 있음.

하지만 Marshal.SizeOf(typeof(IntPtr)) 보다는
Marshal.SizeOf<IntPtr>()이 warning이 뜨지 않음.


https://msdn.microsoft.com/ko-kr/library/0t7xwf59(v=vs.110).aspx
다음 예제에서는 읽기 / 쓰기를 사용 하 여 관리 되지 않는 배열 하는 방법의 ReadIntPtr  WriteIntPtr 메서드.
static void ReadWriteIntPtr()
{
    // Allocate unmanaged memory. 
    int elementSize = Marshal.SizeOf(typeof(IntPtr));
    IntPtr unmanagedArray = Marshal.AllocHGlobal(10 * elementSize);

    // Set the 10 elements of the C-style unmanagedArray
    for (int i = 0; i < 10; i++)
    {
        Marshal.WriteIntPtr(unmanagedArray, i * elementSize, ((IntPtr)(i + 1)));
    }
    Console.WriteLine("Unmanaged memory written.");

    Console.WriteLine("Reading unmanaged memory:");
    // Print the 10 elements of the C-style unmanagedArray
    for (int i = 0; i < 10; i++)
    {
        Console.WriteLine(Marshal.ReadIntPtr(unmanagedArray, i * elementSize));
    }

    Marshal.FreeHGlobal(unmanagedArray);

    Console.WriteLine("Done. Press Enter to continue.");
    Console.ReadLine();
}