객체 초기화
새 오브젝트를 생성하면 내부의 속성 중 하나 이상에 값을 할당해야 합니다.
C# 3.0 이후에는 가독성 향상과 코드 단축을 위해 개체 자체의 초기화가 가능해졌습니다.
1 2 3 | Customer c = new Customer(); c.Name = "James"; c.Address = "204 Lime Street"; | cs |
이와 같은 소스를 한 줄로 압축할 수 있습니다.
1 2 3 4 5 | Customer c = new Customer { Name="James", Address = "204 Lime Street" }; | cs |
The using statement
자주 글꼴, 파일 핸들, 네트워크 리소스 등을 위해 시스템 자원을 사용합니다.
이런 리소스 등을 사용할 때 (Resource, You use it, dispose - 리소스, 할당 후 사용과 해제)란 중요한 점이 있지만, 메모리나 낭비되는 리소스들을 위한 Dispose 작업은 다들 잊어버립니다.
이런 리소스 등을 사용할 때 (Resource, You use it, dispose - 리소스, 할당 후 사용과 해제)란 중요한 점이 있지만, 메모리나 낭비되는 리소스들을 위한 Dispose 작업은 다들 잊어버립니다.
1 2 3 4 5 6 7 8 9 10 | // 1. Allocation of the object Font font1 = new Font("Arial", 10.0f); try{ // 2. The bit where we use the resource }finally{ // 3. Disposal of the object if (font1 != null) ((IDisposable)font1).Dispose(); } | cs |
그래서 Using 문을 사용해 코드를 축약합니다.
1 2 3 4 5 6 | // Allocate the resource using(Font font1 = new Font("Arial", 10.0f)) { // The bit where we use the resource } // Disposal is automatic | cs |
using문은 실제 자원을 할당하고 관리하는 .NET 개체인데, "IDisposable" 인터페이스를 구현해 리소스 관리가 가능해 위와 같이 선언만 해놓으면 저절로 자원 관리가 됩니다.
Nullable objects
변수는 값을 가지고 있어야 하고, 비어있으면 안 됩니다.
때에 따라 비어야 할 때도 있고, 정의되지 않았을 경우 null을 할당하는 것이 편하기도 하며, .NET 2.0에서부터 Nullable을 도입했는데, 사용 예는 아래와 같습니다.
1 2 | Nullable<int> x = null; int? x = null; | cs |
변수를 정의한 다음 ?를 넣고, 타입은 Nullable로 감싸서 사용합니다.
int? 자세한 설명 : http://www.csharpstudy.com/CSharp/CSharp-nullable.aspx
Automatic Properties
속성은 일반적으로 Getter과 Setter로 외부에 노출이 되고, 이를 이용해 값들을 할당합니다.
1 2 3 4 5 6 7 8 9 | public class Person { private string _firstName; public string FirstName; { get { return _firstName; } set { _firstName = value; } } } | cs |
C# 3.0에서부터 자동 속성이 추가되어, 아래처럼 사용할 수 있습니다.
1 2 3 4 5 6 7 8 | public class Person { public string Firstname { get; set; } } | cs |
C#의 컴파일러는 자동으로 백업되는 변수를 생성, 올바른 설정, 속성 설정 등을 수행하기 때문에, Public 클래스 대신에 String 변수를 생성할 수 있습니다.
C# 6 이상 버전에서는 필드와 유사하게 자동 구현 속성을 초기화할 수 있습니다.
public string FirstName { get; set; } = "Jane";
참고 : https://docs.microsoft.com/ko-kr/dotnet/csharp/programming-guide/classes-and-structs/auto-implemented-properties
타입 유추
일반적으로 C#에선 아래와 같이 정의를 합니다.
1 | string MyString = “Hello World”; | cs |
=의 우측에 하나의 데이터 타입(string)을 적어 선언하는 건 너무나 일반적입니다.
근데, 이런 작업을 컴파일러가 대신할 순 없을까요?
1 | var MyString = “Hello World”; | cs |
바로 위의 코드 또한 "MyString"라는 문자열 변수를 생성합니다. 이런 일반적인 상황에서 유추(inference)를 통해 성능이 향상되진 않습니다.
컴파일 시, 어떤 작업 과정이든 데이터 타입에 대해선 먼저 생각하진 않습니다. 아래의 예를 통해 유추에 대해 알아볼 수 있습니다.
1 2 3 4 | var SeniorStaff = Employees.Where(s => s.Age > 35); foreach(var Member in SeniorStaff) Console.WriteLine("Name: {0} Age: {1}",Member.Name,Member.Age); | cs |
람다 표현식(Lambda)
코드를 읽기에 난해할 수 있다는 단점이 있으나 내부적으로 구동하는 데 있어선 아주 좋은 방법입니다.
1 | Func mySeniorStaffFilter = delegate(int a) { return a > 35; }; | cs |
위의 코드에선 직원의 수가 35보다 많다면 True를 반환합니다. 람다 표현 식으로는 좀 더 간결하고 (여기서는)읽기 쉽게 같은 의미를 표현할 수 있습니다.
1 | Func mySeniorStaffFilter = a => a > 35; | cs |
델리게이트를 이용하면 조금 더 코드를 멋지게 꾸밀 수도 있습니다.
1 | var SeniorStaff = Employees.Where(s => s.Age > 35); | cs |
string.IsNullOrEmpty
문자열이 비었는지 확인하려면 string.IsNullOrEmpty 함수를 사용해서 반환 값을 확인하세요.
1 2 3 4 | if (String.IsNullOrEmpty(s) == true) return "is null or empty"; else return String.Format("(\"{0}\") is not null or empty", s); | cs |
문자열의 대소문자 구분
때로는 Case(형식, 형태 등 변수의 속성)를 무시하는 문자열 비교 방법이 필요합니다. 일반적, 또는 전통적으로 문자열 비교 시 전체를 대문자나 소문자로 변환한 후 비교를 합니다.
1 | str1.ToLower() == str2.ToLower() | cs |
그렇지만 반복적으로 이를 이용하다 보면, 퍼포먼스 병목 현상이 벌어지기도 합니다. 대신에, String.Compare() 함수를 사용하면 프로그램의 수행 속도를 향상할 수 있습니다.
두 개의 문자열을 비교하면서 단순한 Case들은 무시하게 됩니다.
1 | string.Compare(str1, str2, true) == 0 //Ignoring cases | cs |
0 이 반환된다면 두 문자열은 서로 같다는 뜻입니다.
ArrayList를 List<>로 교체하기
ArrayList는 여러 종류의 개체들을 다루기에 좋습니다.
그렇지만, ArrayList에 삽입되는 개체(변수)가 같은 타입이라면, 굳이 ArrayList를 고집할 필요 없이 List<>로 교체해서 성능을 향상할 필요가 있습니다.
1 2 3 4 | ArrayList intList = new ArrayList(); intList.add(10); return (int)intList[0] + 20; | cs |
예를 들어, 이런 소스 코드를, 입력 목록의 변수 유형만 변경해 줍니다.
1 2 3 4 | List<int> intList = new List<int>(); intList.add(10) return intList[0] + 20; | cs |
변수 타입을 별도로 캐스트 해줄 필요가 없어집니다. 성능 향상을 꾀할 수 있는 부분은 Integer와 같은 기본 데이터 타입들입니다.
+ ArrayList의 경우 Object 에 의한 참조를 사용하는 방식임으로 암시적 박싱이 일어나게 됨으로 성능상 느리다
&&와 || 사용하기
문장을 빌드할 땐 간단하게, &&, ||를 사용해 보세요(Visual Basic에서는 AndAlso, OrElse). 코드가 적어질 수 있고, 이 적은 코드는 향상된 성능뿐만 아니라 런타임 오류를 방지할 수도 있습니다.
아래는 간단한 예입니다.
1 | if (object1 != null && object1.runMethod()) | cs |
object1은 NULL일 경우 object1.runMethod()가 실행되지 않습니다.
언제 StringBuilder를 사용해야 할까요?
StringBuilder 객체는 일반 문자열 함수보다 더 빠른 문자열 처리 속도를 보유하고 있습니다.
StringBuilder는 기다란 문자열을 처리하는데 아주 좋은 클래스이며, 문자열로 처리할 수 있는 부분을 StringBuilder로 대체하면 C# 소스 코드가 더 적은 리소스를 사용하고, 가독성도 높아질 수 있습니다.
문자열과 StringBuilder 객체를 효율적으로 사용함으로써 소스 코드를 최적화할 수 있습니다.
똑똑한 Try-Catch
Try-Catch문은 예를 들면, 웹이나 디바이스에 접근하는 예외를 프로그래머가 제어하기 위해서 사용이 됩니다.
하지만, Try-Catch문 때문에 소스 코드의 수행 시간은 늘어지니, 최대한 Try-Catch문의 코드는 단순하게 구성해야 합니다.
Replace Division
C#에선 Division의 Replace가 상대적으로 느립니다. 한 가지 방법으론 C#의 소스 코드를 최적화하기 위해 Multiplication-shift operation 부분을 다른 방식으로 대체하는 겁니다.
출처 1 - 10 C# Shorthands that improve productivity (링크 깨짐)
출처 2 - 7 Ways To Optimize C# Code
'프로그래밍(Programming) > C#' 카테고리의 다른 글
Automatic Property 자동으로 구현된 속성 (0) | 2017.09.19 |
---|---|
int? , Nullable 타입 (0) | 2017.09.19 |
String 문자열(C# 프로그래밍 가이드) (0) | 2017.09.18 |
제네릭 Collection(컬렉션) 개체 (0) | 2017.09.08 |
제너릭의 장점과 boxing & unboxing (0) | 2017.09.08 |