C #의 숨겨진 기능? [닫은]


1475

질문 에서 다음을 배운 후에 이것은 내 마음에 왔습니다 .

where T : struct

C # 개발자는 모두 C #의 기본 사항을 알고 있습니다. 선언, 조건부, 루프, 연산자 등을 의미합니다.

우리 중 일부는 Generics , anonymous types , lambdas , LINQ 등과 같은 것들을 마스터했습니다 .

그러나 C # 팬, 중독자, 전문가조차 거의 알지 못하는 C #의 가장 숨겨진 기능이나 요령은 무엇입니까?

지금까지 공개 된 기능은 다음과 같습니다.


키워드

속성

통사론

언어 특징

Visual Studio 기능

뼈대

방법 및 속성

팁 & 트릭

  • Andreas HR Nilsson의 이벤트 핸들러를위한 멋진 방법
  • John의 대문자 비교
  • dp에 의해 반영되지 않은 익명 유형에 액세스
  • Will에 의해 컬렉션 속성을 느리게 인스턴스화하는 빠른 방법
  • roosteronacid의 JavaScript와 같은 익명 인라인 함수

다른

답변:


752

이것은 C # 자체는 아니지만 실제로 System.IO.Path.Combine()사용해야하는 사람을 보지 못했습니다 . 실제로 전체 Path 클래스는 실제로 유용하지만 아무도 사용하지 않습니다!

모든 프로덕션 앱에는 다음과 같은 코드가 있어야한다고 생각합니다.

string path = dir + "\\" + fileName;

584

람다 및 형식 유추 가 과소 평가되었습니다. Lambdas는 여러 명령문을 가질 수 있으며 다음같이 호환 가능한 대리자 객체로 자동으로 두 배가 됩니다 (서명이 일치하는지 확인).

Console.CancelKeyPress +=
    (sender, e) => {
        Console.WriteLine("CTRL+C detected!\n");
        e.Cancel = true;
    };

참고 나는이 없다고 new CancellationEventHandler도 내가의 유형을 지정해야 할 sender그리고 e그들이 이벤트에서 추론 가능한 것. 이것이 전체를 작성하는 데 덜 성가신 이유 delegate (blah blah)이며 매개 변수 유형을 지정해야합니다.

람다는 아무것도 반환 할 필요가 없으며 형식 유추는 이와 같은 맥락에서 매우 강력합니다.

그리고 BTW, 함수 프로그래밍에서 Lambdas를 만드는 Lambdas 를 항상 반환 할 수 있습니다 . 예를 들어, 다음은 Button.Click 이벤트를 처리하는 람다를 만드는 람다입니다.

Func<int, int, EventHandler> makeHandler =
    (dx, dy) => (sender, e) => {
        var btn = (Button) sender;
        btn.Top += dy;
        btn.Left += dx;
    };

btnUp.Click += makeHandler(0, -1);
btnDown.Click += makeHandler(0, 1);
btnLeft.Click += makeHandler(-1, 0);
btnRight.Click += makeHandler(1, 0);

연결에 유의하십시오. (dx, dy) => (sender, e) =>

이제 함수형 프로그래밍 클래스를 가져 가서 기쁘다. :-)

C의 포인터 이외에, 당신이 배워야 할 다른 근본적인 것이라고 생각합니다 :-)


528

에서 릭 Strahl :

당신은 체인 수 있습니다 ?? 연산자를 사용하여 많은 null 비교를 수행 할 수 있습니다.

string result = value1 ?? value2 ?? value3 ?? String.Empty;

454

별명 제네릭 :

using ASimpleName = Dictionary<string, Dictionary<string, List<string>>>;

ASimpleName대신 을 사용할 수 있습니다 Dictionary<string, Dictionary<string, List<string>>>.

많은 장소에서 동일한 일반적인 크고 긴 복잡한 것을 사용할 때 사용하십시오.


438

에서 C #을 통해 CLR :

문자열을 정규화 할 때는 Microsoft가 대문자 비교를 수행하기위한 코드를 최적화 했으므로 ToLowerInvariant 대신 ToUpperInvariant를 사용하는 것이 좋습니다 .

동료가 비교하기 전에 항상 문자열을 대문자로 변경 한 적이 있습니다. 나는 왜 그가 소문자로 변환하는 것이 더 "자연 스럽다"고 느끼기 때문에 왜 그렇게하는지 궁금했습니다. 지금 책을 읽은 후 왜 그런지 알고 있습니다.


254
"문자열을 대문자로 변환"하면 두 번째 임시 문자열 객체가 생성됩니다. 나는 이런 종류의 비교가 바람직하지 않다고 생각했는데, 가장 좋은 방법은 다음과 같습니다.
Anthony

32
소문자 문자열에서 수행 할 수없는 대문자 문자열을 비교할 때 어떤 종류의 최적화를 수행 할 수 있습니까? 왜 하나가 다른 것보다 더 적합한 지 이해가되지 않습니다.
Parappa

36
소문자가 아닌 대문자로 변환하면 특정 문화권에서 잘못된 동작을 방지 할 수도 있습니다. 예를 들어, 터키어에서 두 개의 소문자 i는 동일한 대문자 I로 매핑됩니다. 자세한 내용은 Google "turkish i"입니다.
Neil

34
ToUpperInvariant와 ToLowerInvariant의 벤치마킹을 시도했습니다. .NET 2.0 또는 3.5에서 성능의 차이를 찾을 수 없습니다. 확실히 "적극 추천"하는 것이 다른 것을 사용하는 것이 아닙니다.
Rasmus Faber

19
ToUpperInvariant는 모든 문자를 왕복으로 만들기 때문에 선호됩니다. msdn.microsoft.com/en-us/library/bb386042.aspx를 참조 하십시오 . 비교를 위해"a".Equals("A", StringComparison.OrdinalIgnoreCase)
SLaks

408

내가 가장 좋아하는 트릭은 null 병합 연산자 와 괄호를 사용하여 자동으로 컬렉션을 인스턴스화하는 것입니다.

private IList<Foo> _foo;

public IList<Foo> ListOfFoo 
    { get { return _foo ?? (_foo = new List<Foo>()); } }

23
읽기 힘들지 않습니까?
Riri

72
Noo, 읽기가 약간 어렵고 경험이 부족합니다. 그러나 컴팩트하고 프로그래머가 알고 이해해야하는 몇 가지 패턴과 언어 기능이 포함되어 있습니다. 따라서 처음에는 힘들지만 배우는 이유가 있다는 이점이 있습니다.

38
게으른 인스턴스화는 클래스 불변에 대한 생각을 피하는 나쁜 사람 선택이기 때문에 다소 실용적입니다. 또한 동시성 문제가 있습니다.
John Leidegren

17
나는 이것이 나쁜 실천이라고 항상 들었다. 재산을 부르는 것은 그와 같은 일을해서는 안된다. 거기에 설정이 있고 값을 null로 설정하면 API를 사용하는 사람에게는 매우 이상합니다.
Ian

8
@Ofel을 제외하고 ListOfFoo를 null로 설정하는 것은 클래스 계약의 일부가 아니며 좋은 습관이 아닙니다. 그래서 세터가없는 이유입니다. 또한 ListOfFoo는 컬렉션을 반환하지만 결코 null을 반환하지 않습니다. 두 가지 나쁜 일 (세터를 만들고 컬렉션을 null로 설정)을하면 기대가 잘못된다는 매우 이상한 불만입니다. getter에서도 Environment.Exit ()를 사용하지 않는 것이 좋습니다. 그러나 그것은 또한이 답변과 관련이 없습니다.

315

null 이벤트 처리기를 확인하지 마십시오

선언시 이벤트에 빈 대리자를 추가하여 이벤트를 호출하기 전에 항상 null을 검사해야 할 필요성을 억제합니다. 예:

public delegate void MyClickHandler(object sender, string myValue);
public event MyClickHandler Click = delegate {}; // add empty delegate!

당신이 할 수 있습니다

public void DoSomething()
{
    Click(this, "foo");
}

이 대신

public void DoSomething()
{
    // Unnecessary!
    MyClickHandler click = Click;
    if (click != null) // Unnecessary! 
    {
        click(this, "foo");
    }
}

이 주제에 대한 Eric Lippert의 관련 토론 과이 블로그 게시물 (및 가능한 단점) 도 참조하십시오 .


87
이 기술에 의존하고 클래스를 직렬화 해야하는 경우 문제가 발생할 것이라고 생각합니다. 이벤트를 제거한 다음 역 직렬화에서 NullRefference를 얻을 수 있습니다.. 따라서 일을하는 "오래된 방식"을 고수 할 수 있습니다. 더 안전합니다.
sirrocco

16
여전히 이벤트 핸들러를 널로 설정할 수 있으므로 여전히 널 참조를 얻을 수 있으며 여전히 경쟁 조건이 있습니다.
Robert Paulson

64
빠른 프로파일 테스트는 널 테스트가없는 더미 구독 이벤트 핸들러가 널 테스트가있는 구독 취소 이벤트 핸들러 시간의 약 2 배를 소요 함을 보여줍니다. 널 테스트가없는 멀티 캐스트 이벤트 핸들러는 널 테스트가있는 싱글 캐스트 이벤트 핸들러 시간의 약 3.5 배를 차지합니다.
P Daddy

54
이를 통해 항상 자체 가입자를 확보함으로써 널 검사가 필요하지 않습니다. 빈 이벤트 일지라도 원하지 않는 오버 헤드가 발생합니다. 구독자가없는 경우 이벤트를 전혀 발생시키지 않으려면 항상 빈 더미 이벤트를 먼저 시작하는 것은 아닙니다. 이 나쁜 코드를 고려할 것입니다.
Keith

56
위의 의견에서 이유는 끔찍한 제안입니다. 코드를 "깨끗한"것처럼 보이게하려면 확장 메서드를 사용하여 null을 확인한 다음 이벤트를 호출하십시오. 수정 권한을 가진 사람은 분명히이 답변에 단점을 추가해야합니다.
Greg

305

그 밖의 모든 것

1) 암시 적 제네릭 (클래스가 아닌 메서드에만 해당되는 이유)

void GenericMethod<T>( T input ) { ... }

//Infer type, so
GenericMethod<int>(23); //You don't need the <>.
GenericMethod(23);      //Is enough.

2) 하나의 매개 변수가있는 간단한 람다 :

x => x.ToString() //simplify so many calls

3) 익명 유형 및 이니셜 라이저 :

//Duck-typed: works with any .Add method.
var colours = new Dictionary<string, string> {
    { "red", "#ff0000" },
    { "green", "#00ff00" },
    { "blue", "#0000ff" }
};

int[] arrayOfInt = { 1, 2, 3, 4, 5 };

다른 것:

4) 자동 속성은 다른 범위를 가질 수 있습니다.

public int MyId { get; private set; }

상기시켜 주셔서 감사합니다 @pzycoman :

5) 네임 스페이스 별명 (특별한 구분이 필요하지 않음) :

using web = System.Web.UI.WebControls;
using win = System.Windows.Forms;

web::Control aWebControl = new web::Control();
win::Control aFormControl = new win::Control();

14
# 3에서 Enumerable.Range (1,5)
Echostorm

18
int [] nums = {1,2,3};으로 배열을 초기화 할 수 있다고 생각합니다. 1.0 이후로 :)는 "새로운"키워드조차 필요하지 않습니다
Lucas

13
매개 변수가없는 람다 () => DoSomething ();
Pablo Retyk

5
나는 {get; 내부 세트; } 그리고 얻다; 보호 세트; },이 패턴은 일관성이 있습니다.
Keith

7
@Kirk Broadhurst-당신이 맞습니다- new web.Control()이 예제에서도 작동합니다. 이 ::구문은 접두어를 네임 스페이스 별칭으로 취급하도록하여 클래스를 호출 할 수 web있고 web::Control구문은 여전히 ​​작동하지만 web.Control구문은 클래스 또는 네임 스페이스를 확인할지 여부를 알 수 없습니다. 이 때문에 ::네임 스페이스 별칭을 수행 할 때 항상 사용하는 경향이 있습니다 .
Keith

286

나는 "as"키워드를 한동안 몰랐다.

MyClass myObject = (MyClass) obj;

vs

MyClass myObject = obj as MyClass;

두 번째는 obj가 MyClass가 아닌 경우 클래스 캐스트 예외를 throw하는 대신 null을 반환합니다.


42
과도하게하지 마십시오. 많은 사람들이 (ToType) x의 의미를 원하지만 구문을 선호하기 때문에 사용하는 것 같습니다.
Scott Langham

4
더 나은 성능을 제공한다고 생각하지 않습니다. 프로필을 작성 했습니까? (실제로 캐스트가 실패하면 ...하지만 (MyClass) 캐스트를 사용할 때 실패는 예외적입니다.. 아주 드물게 발생하므로 전혀 차이가 없습니다.
Scott Langham

7
일반적인 경우가 캐스트 실패 인 경우에만 더 성능이 우수합니다. 그렇지 않으면 직접 캐스트 (유형) 객체가 더 빠릅니다. 직접 캐스트에서 null을 반환하는 것보다 예외를 throw하는 데 시간이 더 걸립니다.
Spence

15
"as"키워드의 동일한 줄을 따라 "is"키워드도 유용합니다.
dkpatt

28
InvalidCastException을 더 일찍 가질 수 있었을 때이를 악용하고 나중에 NullReferenceException을 발생시킬 수 있습니다.
Andrei Rînea

262

내가 좋아하는 두 가지는 자동 속성이므로 코드를 더욱 축소 할 수 있습니다.

private string _name;
public string Name
{
    get
    {
        return _name;
    }
    set
    {
        _name = value;
    }
}

된다

public string Name { get; set;}

또한 객체 이니셜 라이저 :

Employee emp = new Employee();
emp.Name = "John Smith";
emp.StartDate = DateTime.Now();

된다

Employee emp = new Employee {Name="John Smith", StartDate=DateTime.Now()}

6
자동 속성은 C # 3.0 전용 기능입니다.
Jared Updike

21
자동 속성은 3.0 컴파일러와 함께 도입되었습니다. 그러나 컴파일러는 2.0 코드를 출력하도록 설정할 수 있으므로 제대로 작동합니다. 구형 컴파일러에서 자동 속성으로 2.0 코드를 컴파일하지 마십시오!
Joshua Shannon

74
많은 사람들이 깨닫지 못하는 것은 get과 set이 다른 접근성을 가질 수 있다는 것입니다. 예 : public string Name {get; 개인 세트;}
Nader Shirazie 2016 년

7
자동 속성의 유일한 문제는 기본 초기화 값을 제공 할 수없는 것입니다.
Stein Åsmul

7
@ ANeves : 아닙니다. 해당 페이지에서 : DefaultValueAttribute는 속성 값으로 멤버를 자동으로 초기화하지 않습니다. 코드에서 초기 값을 설정해야합니다. [DefaultValue]디자이너에 사용되므로 속성을 굵게 표시할지 여부를 알 수 있습니다 (기본값은 아님).
Roger Lipscombe

255

일반 유형의 '기본'키워드 :

T t = default(T);

T가 참조 유형 인 경우 '널'이되고, int 인 경우 0이되고, 부울 인 경우 false가됩니다.


4
플러스 : 유형? Nullable <type>의 바로 가기입니다. default (int) == 0이지만 default (int?) == null입니다.
sunside


221

@는 컴파일러가 문자열에서 이스케이프 문자를 무시하도록 지시합니다.

이것을 명확히하고 싶었습니다 ... 이스케이프 문자를 무시하도록 지시하지 않고 실제로 문자열을 리터럴로 해석하도록 컴파일러에 지시합니다.

당신이 가지고 있다면

string s = @"cat
             dog
             fish"

실제로 다음과 같이 인쇄됩니다 (들여 쓰기에 사용되는 공백도 포함합니다).

cat
             dog
             fish

문자열에 들여 쓰기에 사용한 모든 공백이 포함되어 있지 않습니까?
andy

18
그렇습니다. 그대로 문자열이라고합니다.
Joan Venge

4
출력물에 인쇄 될 공간도 표시되어 있으면 더 명확 해집니다. 지금은 줄 바꿈 문자가 인쇄되는 것처럼 보이지만 공백은 무시됩니다.
aleemb

정규식과 긴 SQL 쿼리를 이스케이프 처리하는 데 매우 유용합니다.
ashes999

또한 매핑 {{{}}}대한 유용하고 string.Format().
Ferruccio

220

전 C # (.NET 3.5)이다의 가장 평가에서-과 덜 알려진 기능 중 하나라고 생각 표현의 나무는 , 특히 제네릭 및 주면서과 결합 될 때. 이것은 NInject 및 Moq와 같은 최신 라이브러리가 사용하는 API 작성에 대한 접근 방식입니다.

예를 들어 API로 메소드를 등록하고 API가 메소드 이름을 가져와야한다고 가정 해 봅시다.

이 수업이 주어지면 :

public class MyClass
{
     public void SomeMethod() { /* Do Something */ }
}

이전에는 개발자가 문자열 및 유형 (또는 대체로 문자열 기반)으로이 작업을 수행하는 것이 매우 일반적이었습니다.

RegisterMethod(typeof(MyClass), "SomeMethod");

글쎄, 그것은 타이핑이 부족하기 때문에 짜증납니다. "SomeMethod"의 이름을 바꾸면 어떻게됩니까? 그러나 3.5에서는 강력한 형식 으로이 작업을 수행 할 수 있습니다.

RegisterMethod<MyClass>(cl => cl.SomeMethod());

RegisterMethod 클래스는 다음 Expression<Action<T>>과 같이 사용 합니다.

void RegisterMethod<T>(Expression<Action<T>> action) where T : class
{
    var expression = (action.Body as MethodCallExpression);

    if (expression != null)
    {
        // TODO: Register method
        Console.WriteLine(expression.Method.Name);
    }
}

이것이 내가 Lambdas 및 Expression Trees와 지금 사랑하는 큰 이유 중 하나입니다.


3
FieldInfo, PropertyInfo 등과 같은 리플렉션 유틸리티 클래스가 있습니다.
Olmo

예, 훌륭합니다. 나는 EditValue(someEmployee, e => e.FirstName);비즈니스 로직에서와 같은 코드를 작성하기 위해 이와 같은 방법을 사용할 수 있었고 ViewModel 및 View에 대한 모든 배관 로직을 자동으로 생성하여 해당 속성을 편집 할 수 있습니다 (따라서 텍스트 "이름"이있는 레이블 및 사용자가 이름을 편집 할 때 FirstName 속성의 setter를 호출하고 getter를 사용하여 View를 업데이트하는 바인딩) 이것은 C #의 대부분의 새로운 내부 DSL에 대한 기초 인 것 같습니다.
Scott Whitlock

4
나는 이것들이 덜 이해되는 것만 큼 덜 알려지지 않았다고 생각합니다.
저스틴 모건

왜 메소드를 등록해야합니까? 나는 이것을 전에 한번도 사용한 적이 없다-언제 어디서 사용될 것인가?
MoonKnight

209

" 수율 "이 내 마음에 올 것이다. [DefaultValue ()] 와 같은 속성 중 일부 는 또한 내가 좋아하는 것 중 하나입니다.

" var "키워드는 좀 더 잘 알려져 있지만 .NET 3.5 응용 프로그램에서도 사용할있습니다 (.NET 3.5 컴파일러사용하고 출력 2.0 코드로 설정 한 경우). 잘.

편집 : kokos, 지적 해 주셔서 감사합니다 ?? 연산자, 정말 유용합니다. 구글은 조금 어렵다 . 연산자 (C # 참조)


14
기본값의 설명서는 실제로 속성 값을 설정하지 않는다고 말합니다. 비주얼 라이저 및 코드 생성기의 도우미 일뿐입니다.
보리스 칼 렌스

2
DefaultValue의 경우 : 그 동안 일부 라이브러리는이를 사용합니다. ASP.net MVC는 컨트롤러 작업의 매개 변수에 DefaultValue를 사용합니다 (널링 불가능 유형에 매우 유용함). 엄밀히 말하면, 이것은 컴파일러가 아니라 MVC의 코드에 의해 값이 설정되기 때문에 코드 생성기입니다.
Michael Stum

6
의 이름은? 연산자는 "널 병합"연산자
Armstrongest

수율은 내가 가장 좋아하는 것입니다. CAS 또는 어셈블리 서명, 강력한 이름, GAC에 대해서는 아무것도 보지 못합니다. CAS 만 C #이라고 생각하지만 많은 개발자가 보안에 대한 실마리가 없습니다.
BrainSlugs83

198

대부분의 C # 개발자는 '널링 가능'유형에 대해 알지 못하는 경향이 있습니다. 기본적으로 널값을 가질 수있는 기본 요소.

double? num1 = null; 
double num2 = num1 ?? -100;

nullable double을 설정하십시오. num1 을 null로 설정 한 다음 num1 이 null 인 경우 일반 double num2num1 또는 -100으로 설정 하십시오 .

http://msdn.microsoft.com/en-us/library/1t3y8s4s(VS.80).aspx

널 입력 가능 유형에 대해 한 가지 더 :

DateTime? tmp = new DateTime();
tmp = null;
return tmp.ToString();

반환 String.Empty입니다. 검사자세한 내용은 링크를 하십시오


1
DateTime을 null로 설정할 수 없습니다.
Jason Jackson

2
그렇다면 "int"는 System.Int32에 대한 C # 구문 설탕입니까? 실제로 Nullable 형식을 중심으로 작성된 컴파일러 지원이 있으며, 예를 들어 일반 구조체만으로는 수행 할 수없는 null로 설정하고 기본 형식으로 boxing 할 수 있습니다.
P Daddy

4
@P Daddy-예, int는 System.Int32의 구문 설탕입니다. 그들은 int처럼 완전히 상호 교환 가능합니까? === Int32? === Nullable <Int32> === Nullable <int>
cjk

6
@ck : 예, int는 System.Int32의 별칭입니다. null 허용에 대한 별칭은 <T는>,하지만 아닌 단지 문법 설탕. 언어의 정의 된 부분입니다. 별칭은 코드를보다 쉽게 ​​읽을 수있게 해줄뿐만 아니라 모델에 더 잘 맞습니다. Nullable <Double>을 이중으로 표현 하시겠습니까? 따라서 포함 된 값이 Double 유형에서 인스턴스화 된 일부 일반 구조가 아니라 double이라는 관점을 강조합니다. (계속)
P Daddy

3
... 어쨌든, 논쟁은 별칭에 관한 것이 아니라 (어쩌면 유추가 나쁜 것 같지만) 원하는 구문을 사용하는 nullable 유형은 실제로 제네릭 제품이 아닌 언어 기능입니다. as제네릭만으로 nullable (널 (NULL)의 할당 / 할당, 연산자 전달, 기본 유형 또는 널의 권투, 널 병합 및 연산자 와의 호환성) 기능을 모두 재현 할 수는 없습니다 . Nullable <T>만으로는 초보적이며 별과 거리가 멀지 만 언어의 일부인 nullable 유형의 개념은 킥 엉덩이입니다.
P Daddy

193

문서화되지 않은 C # 키워드의 형태로 흥미로운 숨겨진 C # 기능은 다음과 같습니다.

__makeref

__reftype

__refvalue

__arglist

이것은 문서화되지 않은 C # 키워드 (Visual Studio에서도이를 인식합니다!)로 제네릭 이전에보다 효율적인 권투 / 언 박싱을 위해 추가되었습니다. 그것들은 System.TypedReference 구조체와 함께 작동합니다.

가변 길이 매개 변수 목록에 사용되는 __arglist도 있습니다.

사람들이 많이 알지 못하는 것 중 하나는 System.WeakReference- 객체를 추적하지만 가비지 수집기가 여전히 수집 할 수있는 매우 유용한 클래스입니다.

가장 유용한 "숨김"기능은 수익률 반환 키워드입니다. 실제로 숨겨져 있지는 않지만 많은 사람들이 그것에 대해 알지 못합니다. LINQ는이 위에 구축되었습니다. 후드 아래에서 상태 머신을 생성하여 지연 실행 쿼리를 허용합니다. Raymond Chen은 최근에 내부의 세부 사항 에 대해 게시했습니다 .


2
피터 브롬 버그에 의해 문서화되지 않은 키워드에 대한 자세한 내용 . 그것들을 사용해야 할 이유가 있다면 여전히 얻지 못합니다.
HuBeZa

제네릭의 출현과 함께 @HuBeZa에는 __refType, __makeref 및 __refvalue를 사용해야하는 많은 이유가 없습니다. 이들은 주로 .NET 2에서 제네릭 이전의 권투를 피하기 위해 사용되었습니다.
Judah Gabriel Himango

Matt는 .NET 2에 제네릭을 도입함으로써 가치 유형을 다룰 때 권투를 피하는 것이 목적이므로 이러한 키워드를 사용할 이유가 거의 없습니다. HuBeZa로 링크를 참조하십시오, 또한 참조 codeproject.com/Articles/38695/UnCommon-C-keywords-A-Look#ud
유다 가브리엘 희망 고

185

순수하고 안전한 C #의 공용체 (C ++ 공유 메모리 종류)

안전하지 않은 모드와 포인터에 의존하지 않고 클래스 멤버가 클래스 / 구조에서 메모리 공간을 공유하도록 할 수 있습니다. 다음과 같은 클래스가 주어집니다.

[StructLayout(LayoutKind.Explicit)]
public class A
{
    [FieldOffset(0)]
    public byte One;

    [FieldOffset(1)]
    public byte Two;

    [FieldOffset(2)]
    public byte Three;

    [FieldOffset(3)]
    public byte Four;

    [FieldOffset(0)]
    public int Int32;
}

Int32 필드를 조작하거나 그 반대로 바이트 필드의 값을 수정할 수 있습니다. 예를 들어이 프로그램은 다음과 같습니다.

    static void Main(string[] args)
    {
        A a = new A { Int32 = int.MaxValue };

        Console.WriteLine(a.Int32);
        Console.WriteLine("{0:X} {1:X} {2:X} {3:X}", a.One, a.Two, a.Three, a.Four);

        a.Four = 0;
        a.Three = 0;
        Console.WriteLine(a.Int32);
    }

이것을 출력합니다 :

2147483647
FF FF FF 7F
65535

System.Runtime.InteropServices를 사용하여 추가하십시오.


7
@George는 c 공용체 선언을 사용하여 소켓을 통해 레거시 응용 프로그램과 통신 할 때 놀라운 일을합니다.
scottm

2
오프셋 0에서 int 및 float를 말하는 것도 의미가 있습니다. 부동 소수점 숫자를 비트 마스크로 조작하려는 경우 필요한 경우가 있습니다. 특히 부동 소수점 숫자에 대해 새로운 것을 배우고 싶다면.
John Leidegren

2
이것에 대한 성가신 점은 이것을 사용하려는 경우 컴파일러가 init 함수에 모든 변수를 설정하도록 강제하는 구조체입니다. 따라서 다음과 같은 경우 : public A (int int32) {Int32 = int32; } "컨트롤을 호출자에게 반환하기 전에 'One'필드를 완전히 할당해야합니다"라는 메시지가 표시되므로 One = Two = Three = Four = 0을 설정해야합니다. 게다가.
manixrock

2
이것은 주로 이진 데이터와 함께 사용됩니다. 나는 int32 @ 0을 가진 "Pixel"구조체를 사용하고, 4 개의 컴포넌트 @ 0, 1, 2 및 3에 대해 4 바이트를 사용합니다. 이미지 데이터를 빠르고 쉽게 조작하기에 좋습니다.
snarf

57
경고 :이 방법은 엔디안을 고려하지 않습니다. 즉, C # 코드는 모든 컴퓨터에서 동일한 방식으로 실행되지 않습니다. 리틀 엔디안 CPU (최하위 바이트를 먼저 저장)에서는 표시된 동작이 사용됩니다. 그러나 빅 엔디안 CPU에서는 바이트가 예상 한 것과 반대로 나타납니다. 프로덕션 코드에서이 코드를 사용하는 방법에주의하십시오. 코드는 특정 모바일 장치 및 기타 하드웨어로 이식 할 수 없으며 명확하지 않은 방식으로 손상 될 수 있습니다 (예 : 두 파일은 표면적으로 동일한 형식이지만 실제로는 바이트 순서가 반대 임).
Ray Burns

176

키워드 인 변수 이름에 @를 사용합니다.

var @object = new object();
var @string = "";
var @if = IpsoFacto(); 

38
왜 키워드를 변수 이름으로 사용 하시겠습니까? 이것이 코드를 읽기 어렵고 난독하게 만들 것입니다.
Jon

41
음, 거기에있는 이유는 CLI는 멤버 이름으로 C #을 키워드를 사용할 수있는 다른 언어와의 상호 운용성을 위해 그것을 필요로한다는 것이다
마크시다

69
asp.net MVC HTML 도우미를 사용하고 HTML 클래스를 정의하려는 경우 @class를 사용하여 클래스 키워드로 인식되지 않도록 할 수 있습니다.
Boris Callens

31
확장 방법에 좋습니다. public static void DoSomething (this Bar @this, string foo) {...}
Jonathan C Dickinson

45
@zihotki : 잘못되었습니다. var a = 5; Console.WriteLine (@a); 인쇄 5
SLaks

168

finally 블록이나 종료자를 호출하지 않고 프로그램을 종료하려면 FailFast를 사용 하십시오 .

Environment.FailFast()

12
이 방법은 또한 메모리 덤프를 작성하고 Windows 오류 로그에 메시지를 기록합니다.
RickNZ 2009

1
이 메소드를 사용할 때 종료 자 또는 앱 도메인 언로드 이벤트가 호출되지 않습니다.
AwkwardCoder

1
힌트는 +1이지만 C #은 아니며 .NET의 BCL입니다.
Abel

. System.Diagnostics.Process.GetCurrentProcess () 죽여 () 빠른
Tolgahan Albayrak

153

메소드에서 익명 유형을 리턴하고 반영없이 멤버에 액세스

// Useful? probably not.
private void foo()
{
    var user = AnonCast(GetUserTuple(), new { Name = default(string), Badges = default(int) });
    Console.WriteLine("Name: {0} Badges: {1}", user.Name, user.Badges);
}

object GetUserTuple()
{
    return new { Name = "dp", Badges = 5 };
}    

// Using the magic of Type Inference...
static T AnonCast<T>(object obj, T t)
{
   return (T) obj;
}

42
그것은 당신에게 아무것도 얻지 못합니다. 실제로 위험합니다. 여러 유형을 반환하도록 GetUserTuple을 수정하면 어떻게됩니까? 캐스트는 런타임에 실패합니다. C # /. Net의 가장 큰 장점 중 하나는 컴파일 시간 확인입니다. 새로운 유형을 만드는 것이 훨씬 낫습니다.
Jason Jackson

9
@Jason 아마 유용하지 않다고 말했지만 놀랍습니다 (숨겨진 것으로 생각했습니다).
phillips

31
멋지지만 이것은 다소 좋지 않은 디자인 선택처럼 보입니다. 기본적으로 익명 유형을 두 곳에 정의했습니다. 이때 실제 구조체를 선언하고 직접 사용하십시오.
Paul Alexander

6
@George : 그런 컨벤션은 ... struct라고 불릴까요?
R. Martinho Fernandes

2
이 트릭의 이름은 'cast by sample'이며 익명 형식을 반환하는 메서드가 다른 어셈블리에있는 경우 작동하지 않습니다.
desco

146

다음은 정규식 및 파일 경로에 유용한 것입니다.

"c:\\program files\\oldway"
@"c:\program file\newway"

@는 컴파일러가 문자열에서 이스케이프 문자를 무시하도록 지시합니다.


27
또한 @ 상수는 내부 줄 바꿈을 허용합니다. 여러 줄 스크립트를 문자열에 할당 할 때 완벽합니다.
Tor Haugen

11
따옴표를 이스케이프 처리하는 것을 잊지 마십시오. [code] var candy = @ "나는" "빨간색" "사탕 지팡이를 좋아한다."; [/ code]
Dave

5
Path.Combine으로 경로를 만드는 경향이 있습니다. @를 정규식으로 사용합니다!
Dan McClain

6
@new도 키워드 대신 변수입니다 : @this, @int, @return, @interface ... so on :)
IAbstract

이 사람은 어디 근처에 오지 않는다 : 그러나 심지어 C의 # 팬이 중독자, 전문가들은 거의 알고있는 가장 숨겨진 기능 또는 C #을의 트릭은 무엇입니까?
publicgk

141

믹스 인. 기본적으로 여러 클래스에 기능을 추가하려고하지만 모든 클래스에 하나의 기본 클래스를 사용할 수없는 경우 각 클래스가 인터페이스를 구현하도록하십시오 (멤버 없음). 그런 다음, 확장 메서드 쓰기 인터페이스에 대한 , 즉

public static DeepCopy(this IPrototype p) { ... }

물론, 일부 명확성이 희생됩니다. 그러나 작동합니다!


4
네, 이것이 확장 방법의 진정한 힘이라고 생각합니다. 기본적으로 인터페이스 메소드의 구현을 허용합니다.
John Bubriski

NHibernate (또는 Castle ActiveRecord)를 사용하고 컬렉션에 인터페이스를 사용해야하는 경우에도 유용합니다. 이렇게하면 컬렉션 인터페이스에 동작을 제공 할 수 있습니다.
Ryan Lundy

이것이 기본적으로 모든 LINQ 메소드가 구현 된 방식입니다.
WCWedin

다음은 NHibernate 또는 Castle ActiveRecord의 컬렉션 인터페이스와 함께 확장 메소드를 사용하여 위에서 언급 한 것에 대해 설명하는 링크입니다. devlicio.us/blogs/billy_mccafferty/archive/2008/09/03/…
Ryan Lundy

7
그들이 확장 속성을 허용한다면 !!!! 나는 읽기 전용 속성으로 간청하는 확장 방법을 작성하는 것을 싫어했다 ....
John Gibb

130

왜 누군가 Nullable <bool>을 사용하고 싶어하는지 잘 모르겠습니다. :-)

참, 거짓, FileNotFound ?


87
사용자가 예 아니오 질문에 대답 할 것으로 예상되는 경우 질문에 대답하지 않은 경우 널 (null)이 적절합니다.
Omar Kooheji

22
널 입력 가능 유형은 테이블 열이 종종 널 입력 가능한 데이터베이스와의 상호 작용에 편리합니다.
tuinstoel

11
예, 아니오, 아마도?
Dan Blair

21
ThreeState CheckBox의 값 저장
Shimmy Weitzhandler

8
SQL에서와 같이 : 예 / 아니요 / 알 수 없음
erikkallen

116

이 이름은 이름이 잘못 지정된만큼 "숨겨지지"않았습니다.

알고리즘 "map", "reduce"및 "filter"에 많은주의를 기울입니다. 대부분의 사람들이 모르는 점은 .NET 3.5가이 세 가지 알고리즘을 모두 추가했지만 이들이 LINQ의 일부라는 사실을 기반으로하여 매우 SQL 이름을 부여한 것입니다.

"map"=> 선택
한 형태에서 다른 형태로 데이터를 변환합니다

"reduce"=>
집계 값을 단일 결과로 집계

"filter"=> Where
기준에 따라 데이터를 필터링 합니다.

LINQ를 사용하여 반복 및 조건을 취하는 데 사용 된 컬렉션에 대한 인라인 작업을 수행하는 기능은 매우 유용 할 수 있습니다. 모든 LINQ 확장 방법이 어떻게 코드를보다 간결하고 유지 관리하는 데 도움이 될 수 있는지 배우는 것이 좋습니다.


1
선택은 모나드에서 "반환"기능처럼 작동합니다. stackoverflow.com/questions/9033/hidden-features-of-c#405088
Mark Cidade

1
"select"는 SQLish 구문을 사용하는 경우에만 필요합니다. 확장 메소드 구문-someCollection.Where (item => item.Price> 5.99M)을 사용하는 경우 select 문을 사용할 필요가 없습니다.
Brad Wilson

7
@Brad, 그 (여기서)는 필터 연산입니다. 선택하지 않고지도 작업을 시도해보십시오.
Eloff

2
LINQ는 내 의견으로는 C #에서 일어난 큰 일입니다. stackoverflow.com/questions/2398818/…
Leniel Maccaferri

1
집계의 가장 작은 서명은 "감소"기능이고 ​​집계의 중간 서명은 훨씬 더 강력한 "접기"기능입니다!
Brett Widmeier

115
Environment.NewLine

시스템 독립 개행.


10
이것에 대한 성가신 것은 컴팩트 프레임 워크에 포함되어 있지 않다는 것입니다.
Stormenet

14
이것은 응용 프로그램의 호스트 플랫폼에 특정한 것이므로 다른 시스템 용 데이터를 작성하는 경우 \ n 또는 \ r \ n을 적절하게 사용해야합니다.
Mesh

이것은 C # 자체의 기능이 아닌 .NET의 BCL의 일부입니다.
Abel

111

String.Format 표현식 안에 중괄호를 사용하려는 경우 ...

int foo = 3;
string bar = "blind mice";
String.Format("{{I am in brackets!}} {0} {1}", foo, bar);
//Outputs "{I am in brackets!} 3 blind mice"

19
@Kyralessa : 사실, 괄호이지만 "중괄호"는 다른 이름입니다. []대괄호가 있고, <그리고 >꺾쇠 괄호입니다. en.wikipedia.org/wiki/Bracket을 참조하십시오 .
icktoofay

4
당신이 올바른지. 그러나 내가 언급했을 때, "중괄호"라고 말하지 않았습니다.
Ryan Lundy

2
지적하기에 아주 좋은 것입니다. 첫 번째 String.Format은 다음과 같습니다. String.Format ( "{0} 중괄호 안에 있습니다 {1} {2} {3}", "{", "}", 3, "blind mice"); {{and}}를 사용하여 이스케이프 처리가 완료된 것을 알게 되었으면 너무 행복했습니다. :)
Gertjan

Muahahahaa ... .Net에서 이미 3 년 동안 프로그래밍했으며이 사실을 몰랐습니다. : D
Arnis Lapsa

이스케이프 시퀀스와 유사하게 작동하는 "곱슬"괄호 ??
Pratik

104
  1. ?? -통합 연산자
  2. using ( statement / directive )-Dispose를 호출하는 것 이상으로 사용할 수있는 훌륭한 키워드
  3. 읽기 전용 -더 많이 사용해야 함
  4. netmodules-너무 나빠 Visual Studio에서 지원되지 않습니다

6
using을 사용하면 긴 네임 스페이스를보다 편리한 문자열로 별칭을 지정할 수 있습니다. using ZipEncode = MyCompany.UtilityCode.Compression.Zip.Encoding; 자세한 내용은 여기있다 : msdn.microsoft.com/en-us/library/sf0df423.aspx은
데이브 R.

2
정말 같은 것은 아닙니다. Dispose를 호출 할 때 별칭 지정 형식을 사용할 때 using 지시문을 사용할 때 using 문을 사용할 수 있습니다.
Øyvind Skaar

2
(삼항 연산자로했던 것처럼) # 1에 이름을 원한다면, ?? null 병합 연산자라고합니다.
J. Steen

4
@LucasAardvark : J Steen이 언급했듯이 null 통합 연산자라고합니다. 그것을 찾으십시오!
kokos 2016 년

1
검색하려면 ?? : 구글의 시도에서 운영자 google.com/search?q=c%23+%3F%3F+operator
backslash17

103

@ Ed, 나는 nitpicking 이상이 아니기 때문에 이것을 게시하는 것에 대해 약간의 reticent입니다. 그러나 코드 샘플에서 다음을 지적합니다.

MyClass c;
  if (obj is MyClass)
    c = obj as MyClass

'is'를 사용하려는 경우 'as'를 사용하여 안전한 캐스트를 사용하는 이유는 무엇입니까? obj가 실제로 MyClass라는 것을 확인한 경우 늪지 표준 캐스트 :

c = (MyClass)obj

... 실패하지 않을 것입니다.

마찬가지로 다음과 같이 말할 수 있습니다.

MyClass c = obj as MyClass;
if(c != null)
{
   ...
}

나는 .NET의 내장에 대해 충분히 알지 못하지만 본능에 따르면 최대 두 가지 유형의 캐스트 작업을 최대 1로 줄이겠다 고 말합니다. 처리 은행을 어느 쪽이든 깨뜨릴 가능성은 거의 없습니다. 개인적으로 후자의 형식도 더 깨끗해 보입니다.


16
캐스트가 정확한 유형에있는 경우 (객체가 "A"일 때 "A"로 캐스트되지 않음) 캐스트는 "as"보다 ~ 3x FASTER입니다. 파생 된 유형 (객체가 "A"에서 파생 된 "B"인 경우 "A"로 캐스팅)을 캐스팅 할 때 스트레이트 캐스팅은 "as"보다 ~ 0.1x 느립니다. "is", "as"는 바보입니다.
P Daddy

2
아니요, 그러나 "if ((c = obj as MyClass)! = null)"라고 쓸 수 있습니다.
Dave Van den Eynde 12

10
isas사용자 캐스트를하지 않습니다. 따라서 위의 코드는 isobj가 MyClass에서 파생 된 것인지 (또는 묵시적 시스템으로 정의 된 캐스트가 있는지) 운영자 에게 묻습니다 . 또한에 is실패합니다 null. 이 두 가지 경우 모두 코드에 중요 할 수 있습니다. 예를 들어, 다음과 같이 작성할 수 있습니다. if( obj == null || obj is MyClass ) c = (MyClass)obj; 그러나 try { c = (MyClass)obj; } catch { }전자는 사용자 정의 변환을 수행하지 않지만 후자는 수행하기 때문에 엄격하게 다릅니다 . null확인 하지 않으면 전자는 is 일 c때 설정되지 않습니다 . objnull
Adam Luter

2
IL에서 캐스트는 CASTCLASS로 이동하지만 AS / IS는 ISINST 명령으로 이동합니다.
John Gibb

5
나는 캐스팅이에 대한 테스트를 실행 IEnumerable<int>List<int>, 그리고 주조 object( new object()에) IEnumerable<int>직접 캐스트 : 확실히 실수가 없는지 확인하기 위해, 주조 등 6.75ns, : 5.69ns 5.43ns은,은 -> 캐스트로. 그런 다음 잘못된 캐스트 테스트 : 직접 캐스트 : 3125000ns, 캐스트 : 5.41ns 결론 : 1 % 요소에 대해 걱정하지 말고 캐스트가 유효하지 않을 때 is / as를 사용하는지 확인하십시오. 캐시와 비교할 때 예외 (처리 된 경우도)가 매우 느리게 발생하므로 578000 요소가 느려집니다. 마지막 부분, 나머지는 중요하지 않음을 기억하십시오 (.Net FW 4.0, 릴리스 빌드)
Aidiakapi

98

어쩌면 고급 기술은 아니지만 항상 나를 미치게하는 기술입니다.

if (x == 1)
{
   x = 2;
}
else
{
   x = 3;
}

다음과 같이 요약 될 수 있습니다.

x = (x==1) ? 2 : 3;

10
내 그룹에서 삼항 연산자가 금지되었습니다. 나는 왜 그런지 이해하지 못했지만 어떤 사람들은 그것을 좋아하지 않습니다.
Justin R.

13
나는 그것들이 같은 것이 아니기 때문에 성명이 아닌 연산자이기 때문에 추측합니다. 나는 첫 번째 접근 방식을 선호합니다. 보다 일관되고 쉽게 확장 할 수 있습니다. 연산자는 문장을 포함 할 수 없으므로 본문을 확장해야하는 순간 그 삼항 연산자를 if 문으로 변환해야합니다.
kervin

16
x ++로 압축 될 수 있습니다. 무의미하다 ^^
François

5
@Guillaume : x의 모든 값을 설명하려면 : x = 2 + System.Math.Min (1, System.Math.Abs ​​(x-1));
mbeckish 2016

38
그것은 실제로 "조건 연산자"라고 - 그것은이다 는 세 개의 인수를하기 때문에 삼항 연산자. en.wikipedia.org/wiki/Conditional_operator
Blorgbeard는
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.