방프리

24.05.05 Chapter5. 동적 프로그래밍 (Item 47) 본문

C#/More Effective C#

24.05.05 Chapter5. 동적 프로그래밍 (Item 47)

방프리 2024. 5. 5. 09:56

Item 47 : Public API에서는 동적 객체 사용을 최소화하라

dynamic 객체는 건드리는 모든 것을 동적으로 만들어버리기에 사용 시 매우 주의해야 한다. 작업의 대상이 되는 매개 변수 중 하나라도 dynamic이라면 그 결과도 dynamic이 된다. 또한 메서드가 동적 객체를 반환하면 그 객체를 사용하는 모든 것이 동적 객체가 된다.

C#은 기본적으로 정적 타입을 선호하며 일부 영역에 동적 타이핑을 적용한다는 점을 반드시 알고 있어야 한다. 만약 주 타이핑 방식이 동적으로만 이루어진다면 언어 선택에 대한 의구심을 가질 필요가 있다. 동적 프로그래밍은 취지는 좋으나 특성상 런타임에 리소스를 많이 사용해야 한다는 점을 알고 있어야 한다. 또한 public 인터페이스에서는 가능한 제외되어야 한다. 동적 타이핑을 하나의 객체나 혹은 특정 타입 내부로 묶어두어, 동적 타이핑이 프로그래밍의 다른 부분 혹은 객체를 사용하는 다른 포로그램으로까지 감염되는 것을 막을 수 있다.

만약 동적 객체를 인터페이스로 노출해야만 할 때라도 모든 것을 동적으로 만들어서는 안된다.

public class CSVDataContainer
{
    private class CSVRow : DynamicObject
    {
        private List<(string, string)> values = new List<(string, string)>();
        public CSVRow(IEnumerable<string> headers, IEnumerable<string> items)
        {
            values.AddRange(headers.Zip(items,
                (header, value) => (header, value)));
        }
        
        public override bool TryGetMember(
            GetMemberBinder binder, out object result)
        {
            var answer = values.FirstOrDefault(n =>
                n.Item1 == binder.Name);
            result = answer.Item2;
            return result != null;
        }
        
        private List<string> columnNames = new List<string>();
        private List<CSVRow> data = new List<CSVRow>();
        
        public CSVDataContainer(System.IO.TextReader stream)
        {
            var headers = stream.ReadLine();
            columnNames = (from header in headers.Split(',')
                select header.Trim()).ToList();
            var line = stream.ReadLine();
            while (line != null)
            {
                var items = line.Split(',');
                data.Add(new CSVRow(columnNames, items));
                line = stream.ReadLine();
            }
        }
        
        public dynamic this[int index] => data[index];
        public IEnumerable<dynamic> Rows => data;
    }
}

 

Comments