C # (. NET) 디자인 결함 [닫힌]


84

일반적으로 C # 또는 .NET Framework의 가장 큰 디자인 결함은 무엇입니까?

예 : nullable이 아닌 문자열 유형이 없으며 IDataReader에서 값을 가져올 때 DBNull을 확인해야합니다.


어떤 의미에서 이러한 디자인 결함이 있습니까?
Juliet

IDataReader를 사용하면 수동으로 확인하는 대신 IsDBNull을 사용할 수 있습니다
Marc Gravell

9
큐 Jon Skeet가 봉인 된 수업에 대해 이야기합니다.)
johnc

3
확장 메서드를 사용하여 IDataReader를 수정하는 것은 매우 쉽습니다 . weblogs.asp.net/skillet/archive/2008/06/18/… 참조 .
Robert Rossney

@lagerdalek-할 수만 있다면 그 댓글을 +1하겠습니다. 잘 기억 된
Marc Gravell

답변:


39

나는 이 게시물에 단호하게 동의합니다 (ToString이 부족한 사람들을 위해 클래스에 대한 사용자 정의 형식을 제공하는 디버거 속성이 있습니다).

위의 목록 위에 다음과 같은 합리적인 요청을 추가합니다.

  1. nullable 값 형식에 대한 보완으로서 nullable이 아닌 참조 형식,
  2. 구조체의 빈 생성자를 재정의 할 수 있습니다.
  3. 제네릭 타입 제약이 봉인 된 클래스를 지정하도록 허용
  4. 제약으로 사용될 때 임의의 생성자 서명을 요청한 다른 포스터에 동의합니다. 어디 T : new(string)또는 어디T : new(string, int)
  5. 또한 빈 이벤트 목록과 동시 설정 모두에서 이벤트 수정에 대한 다른 포스터에 동의합니다 (후자는 까다 롭지 만).
  6. 연산자는 클래스의 정적 메소드가 아닌 확장 메소드로 정의되어야합니다 (또는 최소한 정적 메소드가 아닌).
  7. 인터페이스에 대한 정적 속성 및 메서드 허용 (Java에는이 기능이 있지만 C #에는 없습니다)
  8. 객체 이니셜 라이저에서 이벤트 초기화 허용 (현재 필드 및 속성 만 허용됨)
  9. "개체 이니셜 라이저"구문은 개체를 만들 때만 사용할 수있는 이유는 무엇입니까? 언제라도 사용 가능하게 만드는 것이 어떻습니까?var e = new Foo(); e { Bar = baz };
  10. 2 차 열거 가능 동작 수정 ,
  11. 모든 컬렉션에는 반복을 위해 변경할 수없는 스냅 샷이 있어야합니다 (예 : 컬렉션을 변경하면 반복자가 무효화되지 않아야 함).
  12. 튜플은 추가하기 쉽지만 " Either<T>" 와 같은 효율적인 폐쇄 형 대수 유형 은 그렇지 않습니다. 따라서 폐쇄 형 대수 유형을 선언하고 철저한 패턴 일치를 적용하는 방법을 좋아합니다 (기본적으로 방문자 패턴에 대한 일급 지원이지만 훨씬 더 효율적입니다. 따라서 열거 형을 취하고 철저한 패턴 일치 지원으로 확장하고 유효하지 않은 경우를 허용하지 마십시오.
  13. 일반적으로 패턴 매칭에 대한 지원을 원하지만 최소한 객체 유형 테스트에 대해서는 지원합니다. 나는 또한 여기 다른 게시물에서 제안한 스위치 구문과 비슷합니다.
  14. System.IO같은 클래스 Stream가 다소 잘못 설계 되었다는 다른 게시물에 동의합니다 . 일부 구현이 필요한 인터페이스 NotSupportedException는 잘못된 디자인입니다.
  15. IList현재보다 훨씬 간단해야합니다. 사실, 이것은 다음과 같은 많은 구체적인 컬렉션 인터페이스에 해당 될 수 있습니다 ICollection.
  16. 예를 들어 IDictionary와 같은 예외가 너무 많은 메서드에서 발생합니다.
  17. Java에서 사용할 수있는 것보다 더 나은 확인 된 예외 형식을 선호합니다 (이 작업을 수행하는 방법에 대해서는 유형 및 효과 시스템에 대한 연구 참조).
  18. 일반적인 메서드 오버로드 해결에서 다양한 성가신 코너 케이스를 수정합니다. 예를 들어, 참조 유형에서 작동하는 두 개의 오버로드 된 확장 메소드를 제공하고 다른 하나는 nullable 구조체 유형에서 작동하고 유형 추론이 어떻게 좋아하는지 확인하십시오.
  19. INotifyPropertyChanged필드 이름을 문자열로 사용하는 인터페이스의 필드 및 멤버 이름을 안전하게 반영하는 방법을 제공 합니다. MemberExpression, 즉 람다를 사용하는 확장 메서드를 사용하여이를 수행 할 수 있습니다 . () => Foo하지만 그다지 효율적이지 않습니다.
    • 업데이트 : C # 6.0 nameof()은 단일 멤버 이름에 대한 연산자를 추가 했지만 제네릭에서는 작동하지 않습니다 ( nameof(T) == "T"실제 형식 인수 이름 대신 수행해야 함 typeof(T).Name))- "경로"문자열을 가져올 수도 없습니다. , 예 : nameof(this.ComplexProperty.Value) == "Value"가능한 응용 프로그램 제한.
  20. 인터페이스에서 연산자를 허용하고 모든 핵심 번호 유형이 구현되도록합니다 IArithmetic. 다른 유용한 공유 운영자 인터페이스도 가능합니다.
  21. 객체 필드 / 속성을 변경하는 것을 더 어렵게 만들거나, 최소한 불변 필드에 주석을 달 수 있도록 허용하고 유형 검사기가이를 강제하도록합니다 (단지 chrissakes에서 getter 전용 속성으로 취급하면 어렵지 않습니다!). 사실 필드와 속성을 더 합리적으로 통합해야합니다. 둘 다 가지는 데는 의미가 없기 때문입니다. C # 3.0의 자동 속성은이 방향의 첫 번째 단계이지만 충분하지 않습니다.
    • 업데이트 : C #에는 readonly키워드가 있고 C # 6.0은 읽기 전용 자동 속성을 추가했지만 변경 불가능한 유형 및 값에 대한 실제 언어 지원만큼 엄격하지는 않습니다.
  22. 선언 생성자를 단순화합니다. 나는 F #의 접근 방식을 좋아하지만, 클래스 이름 대신 단순히 "new"가 필요한 다른 게시물은 적어도 더 좋습니다.

지금은 충분하다고 생각합니다. 이것들은 지난주에 내가 만난 모든 자극입니다. 정말로 마음을 쏟으면 몇 시간 동안 계속할 수있을 것입니다. C # 4.0은 이미 명명 된, 선택적 및 기본 인수를 추가하고 있습니다.

이제 한 가지 비합리적인 요청 :

  1. C # / CLR이 형식 생성자 다형성을 지원할 수 있다면 정말 좋을 것 입니다. 제네릭보다 제네릭,

제발요? :-)


1
# 1과 관련하여 모든 유형에는 일부 기본값이 있거나 특정 유형의 변수 또는 필드가 할당 될 때마다 시스템이 생성자를 실행하는 수단을 제공해야합니다. 후자 (# 2의 파생물)를 선호하지만 가상이 아닌 메서드 / 속성이 널 검사없이 호출되도록 지정하도록 데코 레이팅 할 수있는 경우 # 1을 수용 할 수 있습니다. 이렇게하면 "String"필드와 같은 항목이 마치 null이 아닌 빈 문자열이 기본값 인 것처럼 동작 할 수 있습니다 (String의 정적 "length"함수가 null 문자열에서 호출되면 0을 반환 할 수 있기 때문입니다).
supercat 2011

1
# 2와 관련하여 구조체가 0으로 채우기 이외의 생성자뿐만 아니라 바이트 단위 복사 이외의 복사 생성자를 지정할 수 있다면 일반적으로 유용합니다. 실제로 엔터티가 값 또는 참조 의미를 가질 수 있음을 인식하고 값 유형 힙 개체에 변경 가능, 공유 불변 또는 커밋되지 않은 태그를 허용하는 좋은 작업을 수행 할 수있는 .net과 유사한 프레임 워크를보고 싶습니다. (커밋되지 않은 값 개체는 해당 모드가 처음 CompareExchange에서 변경 가능한 경우 변경되거나 해당 모드가 처음 CompareExchange에서 공유되는 경우 공유 될 수 있습니다.)
supercat 2011

1
훌륭한 포인트! # 1의 경우 유형 시스템 주석이 일반적인 솔루션이지만 T : new ()와 같은 유형 변수를 통해 생성자 제약 조건을 전파하는 것을 선호합니다. Re : # 2, 복사 생성자에 대한 좋은 점이지만 위에서 설명한 라인을 따라 더 일반적인 생성자에 만족할 것입니다. 더 나은 방법은 생성자를 구별 방법으로 완전히 제거하고 단순히 정적 메서드로 만드는 것입니다. 이것은 특히 인터페이스에서 정적 메소드를 허용하는 경우 더 간단하고 일반적인 구성 패턴을 허용합니다. 생성자로서의 정적 방법 + 인터페이스의 정적 방법도 # 1을 해결합니다.
naasking

3
# 3 : 봉인 된 클래스를 일반 유형 매개 변수로 사용하는 이유는 무엇입니까? 예를 들어 Foo <T> 여기서 T : string? # 11 : 좋아요, 그래서 저는 List<T>백만 Ts를 얻었습니다 . 스냅 샷을 효율적으로 촬영할 것을 어떻게 제안합니까? # 21 : readonly키워드를 사용하십시오 .... 여기에 좋은 제안이 있지만 대부분 디자인 결함이 아닌 제안 일뿐입니다.
Qwertie

2
이것은 매우 흥미로운 대답이지만 C # 6 기능으로 업데이트해야한다고 생각합니다. 예 : 항목 19 및 21이 구현되었습니다 =)
eduardobr

72
  • Reset()메서드 IEnumerator<T>가 실수였습니다 (반복자 블록의 경우 언어 사양 에서 예외가 발생하도록 요구 합니다)
  • 배열을 반환하는 리플렉션 메서드는 Eric의 관점에서 실수 였습니다.
  • 배열 공분산은 이상했고 여전히
    • 업데이트 : .NET 4.0이 포함 된 C # 4.0은 일반 인터페이스에 공변 / 반 변성 지원을 추가했습니다 ( IEnumerable<out T>Func<in T, out TResult>과 같지만 구체적인 형식 (예 :) 은 List<T>아님).
  • ApplicationException 오히려 호의적으로 떨어졌습니다-그게 실수였습니까?
  • 동기화 된 컬렉션-좋은 생각이지만 실제로는 유용하지는 않습니다. 일반적으로 여러 작업 ( Contains, then Add) 을 동기화해야 하므로 개별 작업을 동기화하는 컬렉션은 그다지 유용하지 않습니다.
    • 업데이트 : 유형 과는 , , , 등은 .NET 프레임 워크 4.0에 추가 된 - 공장의 위임을 받아 들일 방법이 공장은 키 당 한 번만 호출됩니다 보장하지 않습니다하지만.System.Collections.ConcurrentTryAddGetOrAddTryRemove
  • using/ lock패턴을 더 많이 사용할 수 있습니다 .-아마도 재사용 가능한 (확장 가능한?) 구문을 공유 할 수 있습니다. 을 (를) 반환 IDisposable하고 사용하여 시뮬레이션 할 수 using있지만 더 명확 할 수 있습니다.
  • 반복자 블록 : 인수를 미리 확인하는 간단한 방법이 없습니다 (지연하지 않고). 물론 두 개의 연결 메서드를 작성할 수 있지만 그것은 추합니다.
  • 더 간단한 불변성은 좋을 것입니다. C # 4.0은 약간 도움 되지만 충분하지는 않습니다.
  • "이 ref-type 매개 변수는 null 일 수 없습니다."지원은 없습니다. 그러나 계약 (4.0에서)이이 작업에 어느 정도 도움이됩니다. 그러나 Foo(SqlConnection! connection)(null-check / 주입) 와 같은 구문은 throw좋을 것입니다 (대비 int?등)
  • 제네릭을 사용하는 연산자 및 기본이 아닌 생성자의 지원 부족 C # 4.0 dynamic은을 사용 하여이 문제를 약간 해결 하거나 다음 과 같이 활성화 할 수 있습니다.
  • 확장 에서 while 외부 에서 선언되는 반복기 변수 foreach, 즉 anon-methods / lambda가 반복 당 하나가 아닌 단일 변수를 캡처 함을 의미합니다 (스레딩 / 비동기 등으로 고통 스러움).

IEnumerable! = IEnumerable <object>는 정말 이상합니다
Rauhotz

2
음, IEnumerable은 1.1 숙취입니다. 최소한 LINQ와 함께 .Cast <object> ()를 사용할 수 있습니다.
Marc Gravell

8
BCL 사람들은 그것이 ApplicationException실수 라고 말했습니다 . 그들이 바라는 것처럼 유용하지 않습니다. 그들은 또한 그랬어 System.Exception야한다고 말했다 abstract.
Jay Bazuzi

2
Non-nullable : 정규 참조 유형 T를 nullable이 아닌 T를 취하는 무언가에 전달하는 것은 컴파일 오류 여야합니다! (당신이 int?를 int로 전달할 수없는 것처럼). 물론 다른 방향으로 지나가는 것은 괜찮습니다.
Jay Bazuzi

1
@Jon Harrop : IMHO, 불변 배열과 읽기 전용 배열 참조에 대한 지원이 있어야합니다. 다른 배열 변형에 대해서도 가능합니다 (예 : "크기 조정 가능한 배열"(간접 참조) 또는 오프셋 및 바인딩이있는 배열 참조).
supercat

60

TextWriter는 StreamWriter 의 기본 클래스입니다. 뭐?

그것은 항상 나를 극도로 혼란스럽게 만듭니다.


19
+1 매번 찾아봐야합니다. (Whaddaya 새로운 TextWriter ()를 사용할 수 없음을 의미 합니까?)
Nicholas Piasecki

1
신 이시여 감사합니다 ... 나 뿐이라고 생각했습니다.
IJ Kennedy

? 항상 텍스트를 작성하지만 StreamWriter 만 스트림에 작성합니다. 꽤 간단 해 보입니다.
Jon Hanna

4
StreamWriter라는 이름은 텍스트를 충분히 IMO로 작성한다는 사실을 의미하지 않습니다. 그것은 단지 바이트를 쓰는 것처럼 고립되어 들리고 TextWriter는 (string toWrite)의 api를 바이트로 변환하는 멋진 구현이 될 것입니다. 이제 그것이 StreamTextWriter라고 불렸다면 당연히 분명하지만 약간 길 것입니다. :(
Quibblesome

44

작은 C # pet peev-생성자는 C ++ / Java 구문을 사용하여 생성자가 클래스와 동일한 이름이되도록합니다.

New()아니면 ctor()훨씬 더 좋았을 것입니다.

물론 coderush와 같은 도구를 사용하면 클래스 이름을 바꿀 때이 문제를 덜 수 있지만 가독성 관점에서 New ()는 매우 명확합니다.


음, 새 인스턴스를 만들려는 것이 무엇인지 어떻게 알 수 있습니까?
BlueRaja-Danny Pflughoeft

4
@BlueRaja : Scott은 클래스에서 생성자의 이름을 언급하고 있습니다. class Foo { new(int j) {i = j} int i; }
dalle

ctor () 또는 constructor ()가 더 좋았을 것이라는 100 % 동의하지만 ( New대문자 키워드는 관례에 위배 되지 않음 ), 디자인 결함이라고 부르는 것을 주저합니다. 그들은 기존의 C ++ / Java 개발자를 끌어 들이고 싶었고, 어리석은 오래된 구문 규칙을 많이 빌려서 목표를 달성하는 데 도움이되었을 것입니다.
Qwertie 2012

이 질문과 관련이 있습니다 : stackoverflow.com/questions/32101993/c-sharp-sorted-linkedlist MergeSort, bucketsort 또는 다른 정렬 알고리즘을 사용하여 LinkedList를 단순히 정렬하는 방법은 없습니다 (.NET 만 사용). 임시 구현보다.
CoffeDeveloper

29

당신이 할 수 없다는 것을 이해하지 못합니다

여기서 T : new (U)

따라서 제네릭 유형 T에 기본이 아닌 생성자가 있다고 선언합니다.

편집하다:

나는 이것을하고 싶다 :

public class A 
{
    public A(string text) 
    {

    }
}


public class Gen<T> where T : new(string text) 
{

}

제네릭 유형은 해당 유형의 객체, 즉 인터페이스를 사용하는 방법을 선언합니다. 생성자는 해당 인터페이스의 구현 세부 사항이며 소비자의 관심사가 아닙니다. 매개 변수화 된 인스턴스를 생성해야하는 경우 팩토리를 사용하십시오.
Bryan Watts

정보를 위해 컴파일 시간 검사를 수행 할 수는 없지만 MiscUtil에는 기본이 아닌 생성자 (제네릭에서)를 효율적으로 사용하기위한 일부 코드가 있습니다. 즉 Activator.CreateInstance 또는 리플렉션이 없습니다.
Marc Gravell

말이 안되고 일부 용도로 혼동되기 때문입니다. 그럼에도 불구하고 불변 객체로 작업 할 때 유용 할 수 있습니다.
Pop Catalin

7
일반적으로 멤버 제약이없는 것은 성가신 일입니다.
MichaelGG

3
아멘, 난 항상이 싶었던
스티브에게

20

나는 이것을 처음 언급 한 것이 정말 놀랍습니다.

ADO.NET 형식화 된 데이터 집합은 nullable 형식의 속성으로 nullable 열을 노출하지 않습니다. 다음과 같이 작성할 수 있어야합니다.

int? i = myRec.Field;
myRec.Field = null;

대신 다음과 같이 작성해야합니다. 이것은 어리석은 일입니다.

int? i = (int?)myRec.IsFieldNull() ? (int?)null : myRec.Field;
myRec.SetFieldNull();

이것은 .NET 2.0에서 성가신 일이었고 멋진 깔끔한 LINQ 쿼리에서 위와 같은 jiggery-pokery를 사용해야하므로 훨씬 더 성가신 일입니다.

또한 생성 된 Add<TableName>Row메서드가 nullable 형식의 개념과 비슷하게 무의미 하다는 것도 성가신 일입니다 . 생성 된 TableAdapter메서드가 아니기 때문에 더욱 그렇습니다 .

.NET에는 개발팀이 "좋아요, 우리는 충분히 가까웠습니다. 배송 해주세요!"라고 말한 것 같은 느낌이 들지 않습니다. 그러나 이것은 확실합니다.


전적으로 동의합니다! 이것은 내가 그것을 사용해야 할 때마다 나를 괴롭힌다. 아아! +1
Eyvind

2
최소한 그들이 할 수있는 것은 새로운 DataSetV2 클래스 (잘못된 이름-인수를 위해)를 만드는 것입니다.이 클래스는 전체적으로 DBNull 대신 nullable 값 유형을 사용했습니다.
Christian Hayter

특별한 값을 요구하는 부조리 함을 잊지 말자. DBNull.Value, null그 자체가 NULL을 표현하기에 완벽하게 적절 했을 때 . 다행히 LINQ-to-SQL은 NULL에 대해 null을 사용합니다.
Qwertie 2012

사실 그 부조리 함은 전체 부조리 건물이 세워진 바위입니다.
Robert Rossney 2012

20
  1. 나는 Stream, StringWriter, StringReader, TextReader, TextWriter 클래스의 열렬한 팬이 아닙니다 ... 무엇이 무엇인지 직관적이지 않습니다.
  2. IEnumerable.Reset이 반복기에 대한 예외를 발생시킵니다. 데이터 바인딩시 항상 재설정을 호출하는 타사 구성 요소가 있으며이를 사용하려면 먼저 목록으로 캐스팅해야합니다.
  3. XML Serializer에는 직렬화 된 IDictionary 요소가 있어야합니다.
  4. 나는 HttpWebRequest & FTP API에 대해 완전히 잊었다. 내 고통이 .... (Nicholas가 이것을 상기시켜 주셔서 감사합니다 :-)

편집
5. 또 다른 성가심은 System.Reflection.BindingFlags가 사용하는 방법에 따라 다른 용도로 사용된다는 것입니다. 예를 들어 FindFields에서 CreateInstance 또는 SetField는 무엇을 의미합니까? 이것은 그들이 혼란스러운이 열거 뒤에있는 의미를 오버로드 한 경우입니다.


1
+1 매번 XmlTextWriter, TextWriter 등의 클래스를 찾아야합니다. HttpWebRequest / Response 항목과 동일합니다. 완전히 직관적이지 않은 API입니다.
Nicholas Piasecki

+ 1-1 = 0 : XmlTextWriter 등, 이름에서 정확히 무엇인지 추론 할 수 없다는 데 동의합니다. HttpWebRequest 나는 그것이 매우 직관적이라고 생각하는 것에 동의하지 않습니다.
AnthonyWJones

각각 자신에게 나는 생각합니다. 나는 FTP를 사용하면 그들이 가진 것보다 더 높은 수준의 추상화를 기대할 것이라고 생각합니다.
JoshBerke

15

디자인상의 결함이라고 말할 수 있을지는 모르겠지만, VB에서와 같은 방식으로 람다 식을 추론 할 수 있다면 정말 좋을 것입니다.

VB :

Dim a = Function(x) x * (x - 1)

씨#

이렇게 할 수 있다면 좋을 것입니다.

var a = x => x * (x - 1);

이렇게하는 대신 :

Func<int, int> a = x => x * (x - 1);

그다지 길지 않다는 것을 알고 있지만 Code Golf에서는 모든 캐릭터가 망할 수 있습니다! 그들은 이러한 프로그래밍 언어를 설계 할 때 그것을 고려하지 않습니까? :)


3
Microsoft는 언어를 디자인 할 때 Code Golf를 고려해야합니까?
jrcs3

3
@Ray Burns : VB에서 어떻게 압니까? VB가이를 지원하는데 차이점은 무엇입니까?
BenAlabaster 2009

3
@RayBurns 유형 추론? 1989 년부터 사용하고 있습니다.
RD1

3
Lamdas는 C #에서 Homoiconic입니다. 조각 (int x) => x * (x -1);은 의미 Func<int, int>하거나 의미 할 수 있습니다Expression<Func<int, int>>
Scott Weinstein

3
@BenAlabaster : VB는 후기 바운드 산술 연산자를 지원합니다. C #은 컴파일 타임에이를 해결해야합니다. 그것은 언어의 차이입니다. 예를 들어 VB는 두 개체를 함께 추가 할 수 있습니다. 에 +대해 정의 되지 않았기 때문에 C #은 할 수 없습니다 object.
재귀

14
  1. 은 System.Object의 클래스 :

    • Equals 및 GetHashCode-모든 클래스가 비교 가능하거나 해시 가능한 것은 아니므로 인터페이스로 이동해야합니다. IEquatable 또는 IComparable (또는 유사)이 떠 오릅니다.

    • ToString-모든 클래스를 문자열로 변환 할 수있는 것은 아니므로 인터페이스로 이동해야합니다. IFormattable (또는 유사)이 떠 오릅니다.

  2. ICollection.SyncRoot의 특성 :

    • 열악한 디자인을 조장하고 외부 잠금 장치가 거의 항상 더 유용합니다.
  3. Generics는 처음부터 있어야합니다.

    • 은 System.Collections의 네임 스페이스는 더 많거나 적은 오래된 클래스와 인터페이스를 많이 포함되어 있습니다.

1
1. 이러한 메서드는 너무 일반적이어서 이상한 경우가 괜찮다고 결정했습니다. 누군가가 클래스에서 Object.Equals를 호출 할 수 있는지 여부가 중요합니까? 구현이있을 수도 있고 없을 수도 있으며 다음을 요구하는 것으로 알려져 있습니다. IEquatable, 99 %의 클래스에 대한 IFormattable은 이상합니다.
Guvante

1
예를 들어, 사용자 정의 객체에 코드를 명시 적으로 추가하지 않고도 기본 참조 동등성을 사용하여 사용자 정의 객체를 키로 사용하여 사전을 구성 할 수 있으면 유용합니다. Finalize는 훨씬 더 큰 낭비라고 생각합니다 (더 나은 대안은 완성이 필요한 객체가 iFinalizable을 구현하고 최종화를 위해 명시 적으로 등록하는 것입니다). OTOH, 생성자가 예외를 throw하는 경우 Dispose 호출을 포함하여 iDisposable에 대한 더 많은 고유 한 지원이 있어야합니다.
supercat

1
@supercat : 필요한 모든 것은 EqualityComparer<T>.Default올바르게 업데이트하는 것입니다. 그런 다음 var dict = new Dictionary<object, string>(EqualityComparer<object>.Default)및 둘 다 var dict = new Dictionary<object, string>()참조 비교 / 동등을 사용합니다.
dalle

1
@supercat : 당신이 설명하는 것은 정확히 무엇을 의미 EqualityComparer<T>.Default합니다. 조회 할 때마다 확인할 필요가 없습니다. 비교자는 Dictionary인스턴스에 대한 속성 이며 각각 Dictionary이 사용중인 것을 알고 있습니다.
dalle

1
@supercat : 사전은 가장 일반적인 유형 (예 : 공통 기본 클래스)을 키로 사용해야합니다. 동일한 사전에서 Strings와 DateTime을 모두 사용하면 사용자 정의 비교가 다음과 같이 제공되지 않는 한 참조 비교를 사용하지 않는 한 아무런 의미가 없습니다. 이다. 이 항목의 이름은 "C # (. NET) 디자인 결함"입니다.
dalle

12

저를 짜증나게하는 것 중 하나는 Predicate<T> != Func<T, bool>역설입니다. 둘 다 유형의 대리자 T -> bool이지만 할당과 호환되지 않습니다.


Delegate.Create와 일부 캐스팅을 사용하여 변환을 수행하는 트릭이 있지만 적어도 명시 적 캐스팅을 수행 할 수 있으면 좋을 것입니다 (하지만 암시 적 지원이 부족하다는 것을 이해할 수 있습니다)
Guvante

일반적으로 대표자의 디자인에 결함이 있습니다. 예를 들어 약한 이벤트의 부족 (구독자의 특별한 노력없이 소스 측 약한 이벤트를 구현하는 것은 많은 리플렉션과 ReflectionPermission으로 만 수행 할 수 있습니다. codeproject.com/Articles/29922/Weak-Events-in-C 참조 ), 대리자가 참조 형식이어야한다는 요구 사항에서 비 효율성이 발생합니다 (대리자는 더 빠를 것이고 값 형식이었던 경우 많은 경우에 1/3의 메모리를 사용했을 것입니다. 스택에 전달할 수있는 포인터.)
Qwertie

11

어떤 사람들 (ISV)은 dotNet 런타임이 필요하지 않은 네이티브 실행 파일을 만들기 위해 빌드 타임에 머신 코드로 컴파일하고 링크 할 수 있기를 바랍니다.


실행하기 전에 프로그램을 NGEN 할 수 있어야합니다.
Otávio Décio

런타임의 종속성을 제거하는 것과 동일하지 않습니다. 코드에서 실행되는 첫 번째 JIT 만 저장합니다.
Ed S.


이것을 수행하는 난독 화 도구가 없습니까? exe에 프레임 워크를 포함하므로 배포 할 필요가 없습니다. 이름을 기억할 수 없습니다 ... PreEmptive가 아닙니다 ...
JoshBerke

2
Xenocode의 Postbuild가 그렇게하지 않습니까? Visual Studio가이 작업을 수행 할 수 있다면 좋을 것입니다 ...
BenAlabaster

11

우리는 권리 에 대해 너무 많이 알고 있습니다. OO 기술 있습니다. 디커플링, 계약에 의한 프로그래밍, 부적절한 상속 방지, 적절한 예외 사용, 개방 / 폐쇄 주체, Liskov 대체 가능성 등. 아직 .Net 프레임 워크는 모범 사례를 사용하지 않습니다.

나에게 .Net 디자인의 가장 큰 결함은 거인의 어깨에 서 있지 않습니다. 프레임 워크를 사용하는 수많은 프로그래머에게 이상적이지 않은 프로그래밍 패러다임을 홍보 합니다.

MS가 이에주의를 기울 였다면 소프트웨어 엔지니어링 세계는 이번 10 년 동안 품질, 안정성 및 확장 성 측면에서 큰 도약을 할 수 있었지만 아쉽게도 퇴보하고있는 것 같습니다.


4
목표에 대한 폭언에 +1; 여기에 모든 클래스를 하위 클래스로 분류 할 수 없음, 기본 클래스에 대한 인터페이스 부족, 몇 년 후에도 프레임 워크 버그 수정을 꺼리는 등을 추가 할 것입니다
Steven A. Lowe

1
추격에 나서면 .Net 프레임 워크가 너무 나빠서 어떤 결함이 최악인지 파악하기 어렵다는 말입니까? 나는 벤트 후 기분이 나아지고 MS 팬 보이들에게 외칠 것으로 예상했기 때문에 upvote에 감사드립니다.
Daniel Paull

나는 어느 쪽도 투표하지 않았고, 어쨌든 나는 하향 표를 발행하는 것을 매우 꺼려하지만, 왜 내가 신경 쓰지 않는지 알아 내려고 노력하고 있습니다.
Mike Dunlavey

2
나는 당신이 대답이 아닌 "할 수있는만큼 좋지 않다"고 말하는 것 같아요. 완벽한 것은 없습니다. 세부 사항을 제공하십시오.
jcollum

3
아니, 디자인에 명백히 결함이있는 경우가 많다고 말하고 있는데, 그들이 옳다고 생각할 때 여전히 틀렸다고 생각합니다. 예를 들어 MSDN 포럼에 대한 내 게시물은 다음과 같습니다. social.msdn.microsoft.com/forums/en-US/wpf/thread/…
Daniel Paull

11

C # switch 문이 마음에 들지 않습니다.

나는 이것과 같은 것을 원한다

switch (a) {
  1    : do_something;
  2    : do_something_else;
  3,4  : do_something_different;
  else : do_something_weird; 
}

따라서 더 이상 끊기지 않고 (잊기 쉬움) 다른 값을 쉼표로 구분할 수 있습니다.


실제로 C #의 다른 모든 것과 같이 단일 문이나 중괄호로 묶인 블록이 필요한 경우 더 좋을 것이라고 생각합니다. 통과 할 수있는 기능이 없으면 현재 중단 구문은 약간 어리 석고 범위도 제한하지 않습니다. (AFAIK, 그것은, 나도 몰라 수도)
타마스 Czinege에게

무슨 말인지 이해가 안 돼요. 여기에 '이상적인'switch 문을 게시하십시오. 나는 넘어지지 않고 쉼표로 구분 된 값을 원하지 않습니다.
tuinstoel

8
덧붙여서 OP에 동의합니다. switchC의 의도적으로 불구가 된 버전을 모방하는 모든 언어에서 근본적으로 깨졌습니다 (속도 최적화!). VB는 훨씬 더 나은 요금이지만 패턴 매칭을 사용하는 언어 (Haskell, F #…)보다 여전히 광년 뒤쳐져 있습니다.
Konrad Rudolph

1
tuinostel : switch (a) {case 1 {do_something; } 사례 2 {do_something_else; }} - break 문 치우는이라고 하고 각각의 경우에 대한 적절한 코드 블록을 필요로
타마스 Czinege

2
break는 일반적으로 실수처럼 보이지만 그것을 내보내는 것은 컴파일 오류 아닌가요? C에서 C #으로의 전환을 쉽게하기 위해서만있는 것 같습니다 (자동으로 넘어갈 수없는 교육 개발자라고도 함)
Guvante

10

리스너를 명시 적으로 확인해야하는 C #의 이벤트. 이벤트의 핵심이 아니 었나요? 아무것도 없어도?


1
당신이 그것을 원할 때 이것을위한 설탕이 없다는 것은 성가시다. 나는 그들이 그것을 힘들게하는 이유를 알고있다. 그것은 필요하지 않은 경우 이벤트의 인수를 인스턴스화하지 않도록 장려한다
ShuggyCoUk

흠. 나는 이해하지 못하거나 동의하지 않거나 둘 다 :-). 나는 어떤 것을 인스턴스화하는 것이 낙담했다고 말할 수 없습니다. 이것은 나에게 조기 최적화처럼 냄새가 난다.
Thomas Eyde

경우에 따라 부분 메서드가 실행 가능한 대안입니다.
Robert Harvey

PLUS 모든이 원인을 결합 ... MS는 CAB 수정이 두 가지 문제가 있지만 CAB는 (이벤트 주제와 같은 예를 들어, 문자열이 아닌 열거.) 많은 C #에서 제한 자신 인해의 문제가 - 왜 그냥 느슨하게하지 -결합 이벤트 언어의 일부 !?
BlueRaja-Danny Pflughoeft

9

중첩 / 재귀 반복기 의 끔찍한 (그리고 대부분의 사람들에게는 보이지 않는) O (N ^ 2) 동작 .

나는 그들이 그것에 대해 알고 있고, 그것을 고치는 방법을 알고 있다는 사실에 상당히 당혹스러워 하지만, 포함할만한 충분한 우선 순위를 가지고 있지 않다고 생각합니다.

나는 항상 트리와 같은 구조로 작업하고, 이런 식으로 고비용의 작업을 실수로 도입 할 때 똑똑한 사람들의 코드를 수정해야합니다.

"yield foreach"의 장점은 더 간단하고 쉬운 구문이 정확하고 성능이 좋은 코드를 장려 한다는 것입니다. 이것이 플랫폼의 장기적인 성공을 위해 새로운 기능을 추가하기 전에 열망해야 할 "성공의 구덩이" 입니다.


이것은 O 행동에 대한 직관적 인 기대에 위배되기 때문에 특히 결함이 있습니다. 그래서 많은 사람들을 가두 게 될 것입니다
oefe

7

일부 클래스는 인터페이스를 구현하지만 해당 인터페이스의 많은 메서드를 구현하지 않습니다. 예를 들어 Array는 IList를 구현하지만 9 개 중 4 개 메서드는 NotSupportedException을 throw합니다 . .aspx


음, 배열의 요소 수를 변경할 수 없으므로 Add, Clear, Insert 및 Remove (At)가 수행 할 수있는 작업은 없지만 NotSupported를 throw합니다 ... 사실, true를 반환하는 IList의 모든 구현을 기대합니다. IsFixedSize는 그들에게 던질 것입니다.
CB

@CB가 파티에 조금 늦었 나봐요 :)하지만 Array가 "IList"를 만족시킬 수 없다면 어차피 구현할까요? 그것은 SOLID 원칙의 L 위반입니다.
Winger Sendon

7

인터페이스의 정적 멤버 및 중첩 유형.

인터페이스 부재는 인터페이스에 특정한 타입의 파라미터 (가질 때 특히 유용 enum). 인터페이스 유형에 열거 유형을 중첩하는 것이 좋습니다.


1
다른 제안과 매우 유사하지 않습니까?
RCIX 2009-06-30

1
아니요, 이것은 C # 언어에 관한 것이고 다른 하나는 프레임 워크에 관한 것입니다. 모든 사람이 구별에 관심이있는 것은 아니므로이 것은 허용되는 것에 관한 것이고 다른 하나는 제공되는 것에 관한 것이라고 말하겠습니다.
Jay Bazuzi

6

이벤트의 매우 위험한 기본 특성. 이벤트를 호출 할 수 있고 구독자가 제거되어 일관성이없는 상태에 있다는 사실은 끔찍합니다. 주제에 대한 자세한 내용은 Jon SkeetEric Lippert의 우수한 기사를 참조하십시오.


이벤트가 기본적으로 스레드로부터 안전하지 않더라도 상관 없습니다 (단일 스레드 코드에서 성능을 향상시킬 수 있음). 어리석은 것은 추가 / 제거가 기본적으로 안전하지만 이벤트를 발생시키는 자연스러운 방법은 안전하지 않으며 쉽게 안전하게 만들 수있는 기능이 없다는 것입니다.
Qwertie 2012

@Qwertie : 더 어리석은 것은 꽤 오랫동안 추가 / 제거가 잠금을 사용하지만 여전히 스레드로부터 안전하지 않다는 것입니다.
supercat

6
  • null 어디에나.

  • const 아무데도.

  • API는 일관성이 없습니다. 예를 들어 배열을 변경하면 반환 void되지만에 추가 StringBuffer하면 동일한 mutable 이 반환 StringBuffer됩니다.

  • 컬렉션 인터페이스는 불변 데이터 구조와 호환되지 않습니다. 예를 들어 Addin System.Collections.Generic.IList<_>은 결과를 반환 할 수 없습니다.

  • 구조적인 입력하면 쓸 수 있도록 System.Windows.Media.Effects.SamplingMode.Bilinear대신의 Bilinear.

  • IEnumerator불변이어야 할 때 클래스에 의해 구현 된 가변 인터페이스 struct.

  • 평등과 비교 엉망입니다 : 당신이있어 System.IComparable하고 Equals그러나 당신은 또한있어 System.IComparable<_>, System.IEquatable, System.Collections.IComparer, System.Collections.IStructuralComparable, System.Collections.IStructuralEquatable, System.Collections.Generic.IComparerSystem.Collections.Generic.IEqualityComparer.

  • 튜플은 구조체 여야하지만 구조체는 꼬리 호출 제거를 불필요하게 금지하므로 가장 일반적이고 기본적인 데이터 유형 중 하나가 불필요하게 할당되고 확장 가능한 병렬 처리가 파괴됩니다.


CLR에는 구조적 유형이 없지만 유형 추론 또는 "심볼"이라는 Ruby 기능과 구조적 유형이 혼합 된 것 같습니다. 구조적 유형은 CLR이 Func <int, bool> 및 Predicate <int>가 동일한 유형이거나 적어도 암시 적으로 변환 가능한 것으로 간주하는 경우입니다.
Qwertie

비교라고하면 Comparer <T>를 잊지 마세요!
Qwertie

@Qwertie 저는 OCaml의 다형성 변형과 같은 프로그래밍 언어 기능을 언급했습니다. OCaml의 LablGL 라이브러리에는 그래픽의 맥락에서 유용한 구조적 유형의 많은 흥미로운 예가 있습니다. 유형 추론과 관련이 없으며 기호와 접선 적으로 만 관련됩니다.
JD

1
불변 구조체를 IEnumerator어떻게 사용 합니까?
supercat 2012

5

열거 형으로 0 달빛

enum의 특성 : http://blogs.msdn.com/abhinaba/archive/2007/01/09/more-peculiarites-of-enum.aspx

이 좋은 예에서 설명한대로 : http://plus.kaist.ac.kr/~shoh/postgresql/Npgsql/apidocs/Npgsql.NpgsqlParameterCollection.Add_overload_3.html

내 제안, "@"기호를 잘 사용하십시오.

대신에:

if ((myVar & MyEnumName.ColorRed)! = 0)

이것을 사용하십시오 :

if ((myVar & MyEnumName.ColorRed)! = @ 0)


1
하나 열거는 C #하지 않았다 권리 동안 자바가했던 몇 가지 중 하나입니다
BlueRaja - 대니 Pflughoeft

5

이미 다른 사람들이 만든 좋은 점의 긴 목록에 추가하려면 :

  • DateTime.Now == DateTime.Now 대부분의 경우이지만 모든 경우는 아닙니다.

  • String불변 인 것은 구성과 조작을위한 많은 옵션을 가지고 있지만 StringBuilder(변할 수있는) 그렇지 않습니다.

  • Monitor.EnterMonitor.Exit 해야하고 인스턴스 메서드, 그래서 대신 잠금에 대해 특정 오브젝트를 newing, 그럴 수있어 새로 만들기 Monitor가에 및 잠금.

  • 소멸자는 소멸자로 명명되어서는 안됩니다. ECMA 사양에서는이를 종료 자라고 부르며 C ++ 군중에게는 훨씬 덜 혼란 스럽지만 언어 사양에서는 여전히이를 소멸 자라고합니다.


3
DateTime.Now하나는 나머지 세계의 가장 확실한 경쟁 조건, 그러나 +1
BlueRaja - 대니 Pflughoeft

경쟁 조건이 아니라 속성으로 만든 사실입니다. 속성은 필드와 똑같이 보이므로 IMO는 다소 놀라운 동작입니다.
Brian Rasmussen

4
@Brian Rasmussen : DateTime.Now는 읽기가 아니라 외부 요인에 의해 변경되기 때문에 상당히 적절한 속성입니다. SomeForm.Width와 같은 속성을 읽은 다음 사용자가 양식의 크기를 조정 한 후 다시 읽으면 두 번째 읽기의 값이 달라집니다. 첫 번째 DateTime.Now가 두 번째가 읽은 값에 영향을 미칠 정도로 실행하는 데 시간이 오래 걸릴 수 있지만 이러한 효과는 실행 시간이 동일한 다른 함수와 다르지 않습니다.
supercat

4

우리가 속성을 사용하는 방식은 때때로 나를 짜증나게합니다. 나는 그것들을 Java의 getFoo () 및 setFoo () 메소드와 동등하다고 생각하고 싶습니다. 하지만 그렇지 않습니다.

는 IF 속성 사용 지침의 직렬화가 작동 할 수 있도록 속성 수 있어야 상태, 임의의 순서로 설정해야합니다 그들은있는 거 세터시의 검증을위한 쓸모. 개체가 잘못된 상태가되는 것을 방지하려는 배경에서 온 경우 속성은 솔루션이 아닙니다. 때때로 나는 그들이 공공 회원들보다 얼마나 더 나은지 보지 못합니다. 우리는 부동산에서 해야 할 일의 종류가 너무 제한 되어 있기 때문입니다.

이를 위해 저는 항상 속성 구문을 어떻게 든 확장 할 수 있기를 바랐습니다 (대부분 여기에서 큰 소리로 생각하고 있습니다. 저는 이런 식으로 할 수 있기를 바랍니다). 다음과 같이 상상해보십시오.


private string password;

public string Password
{
    // Called when being set by a deserializer or a persistence
    // framework
    deserialize
    {
       // I could put some backward-compat hacks in here. Like
       // weak passwords are grandfathered in without blowing up
       this.password = value;
    }
    get
    {
       if (Thread.CurrentPrincipal.IsInRole("Administrator"))
       {
           return this.password;
       }
       else
       {
           throw new PermissionException();
       }
    }
    set
    {
       if (MeetsPasswordRequirements(value))
       {
           throw new BlahException();
       }
       this.password = value;
    }
    serialize
    {
        return this.password;
    }
}

그것이 유용한 지 또는 액세스하는 것이 어떻게 생겼는지 잘 모르겠습니다. 하지만 속성으로 더 많은 작업을 수행하고 실제로 get 및 set 메서드처럼 처리 할 수 ​​있기를 바랍니다.


3
나는 그들이 ISerializable 인터페이스와 암시 적 생성자를 제공한다고 믿습니다. 즉, serializer가 속성을 호출하는 것을 원하지 않을 때도 마찬가지입니다. 조금 더 많은 작업을 수행했지만 이미 대부분의 작업을 방법으로 수행하고있는 것 같습니다.
Guvante

4

확장 방법은 좋지만 믹스 인의 주제에 대해 실제 믹스 인으로 더 깨끗하게 해결할 수있는 문제를 해결하는 추악한 방법입니다 (내가 말하는 내용을 보려면 루비를보세요). 그것들을 언어에 추가하는 정말 좋은 방법은 제네릭을 상속에 사용할 수있게하는 것이었을 것입니다. 이를 통해 기존 클래스를 멋진 객체 지향 방식으로 확장 할 수 있습니다.

public class MyMixin<T> : T
{
    // etc...
}

다음과 같이 문자열을 확장하는 데 사용할 수 있습니다.

var newMixin = new MyMixin<string>();

예를 들어 언어 내부에서 AOP와 유사한 기능을 허용하는 래핑과 같이 메서드를 재정의 할 수 있기 때문에 확장 메서드보다 훨씬 강력합니다.

폭언 죄송합니다 :-)


5
흥미롭지 만 확장 방법을 선호합니다. 문자열에 대한 확장 메서드가 포함 된 라이브러리를 얻는 경우 새 항목을 얻기 위해 모든 문자열 참조를 MyMixin <string>으로 변경할 필요가 없습니다. 확실히 사소하지만 메서드의 투명한 추가는 확장 메서드를 멋지게 만드는 이유입니다.
RCIX 2009-06-30

BTW 이미 작동한다는 것을 알고 계셨습니까?
RCIX 2009-06-30

2
내가 LINQ 이런 식으로 일할 수있는 표시되지 않습니다
대니 Pflughoeft - BlueRaja

2
@RCIX : Mixins는 확장 메서드가 작동해야한다고 생각했던 것처럼 들립니다. 확장 메서드를 암시 적으로 만드는 문제는 실제 클래스 멤버가 확장 메서드보다 우선 순위를 가져야한다는 것입니다. 확장 메서드 Graphics.DrawParallelogram (Pen p, Point v1, Point v2, Point v3)이 정의되고 나중에 다른 순서로 점을 사용하는 System.Graphics에 DrawParallelogram 함수가 추가되면 확장 메서드를 사용하는 코드는 경고. BTW, 확장 메서드 (예 : object..method ())에 점 두 개를 사용하는 데 문제가 있었습니까?
supercat

3

Microsoft는 프레임 워크의 명백한 버그를 수정하지 않으며 최종 사용자가 수정할 수 있도록 후크를 제공하지 않습니다.

또한 런타임에 .NET 실행 파일을 바이너리 패치 할 수있는 방법이 없으며 네이티브 라이브러리를 바이너리 패치하지 않고 (로드 호출을 가로 채기 위해) .NET 프레임 워크 라이브러리의 비공개 버전을 지정할 방법이 없으며 ILDASM은 재배포 할 수 없으므로 자동화 할 수 없습니다. 어쨌든 패치.


1
어떤 명백한 프레임 워크 버그를 의미합니까?
Robert Rossney

1
# 1 스크롤 가능한 컨트롤의 부분적으로 보이는 자식 컨트롤을 클릭합니다. 컨트롤이 MouseDown 이벤트를 받기 전에보기로 이동하여 클릭이 예상과 다른 컨트롤의 다른 위치에있게됩니다. 드래그 작업도 트리거하는 트리 뷰에서 더 나쁩니다.
Joshua


3
  • null 변수에 대한 확장 메서드를 호출 할 수 있어야합니다.

    개체 a = null; a.MyExtMethod (); // 이것은 호출 가능합니다. MyExtMethod를 정의한 어딘가에 가정합니다.

    편리 할 수는 있지만 null 참조 예외 항목에서는 모호합니다.

  • 하나의 명명 '결함'. System.configuration.dll에서 "configuration"의 'C'는 대문자 여야합니다.

  • 예외 처리. 예외는 Java에서와 같이 강제로 포착되거나 throw되어야하며 컴파일러는 컴파일시이를 확인해야합니다. 사용자는 대상 호출 내의 예외 정보에 대한 주석에 의존해서는 안됩니다.


3
하지만 매우 편리합니다. 매개 변수 검사를위한 "ThrowIfNull` 확장 메서드가 있습니다. ;-p
Marc Gravell

2
할 수있어? ugh ThrowIfNull 그것은 흥미로운 확장이지만 이것은 단지 잘못된 것 같습니다.
JoshBerke

1
일반 CLR에서는 null 참조에 대해 인스턴스 메서드를 호출 할 수 있으며 메서드가 개체 또는 해당 필드에 액세스하지 않으면 호출에서 null 참조 예외가 발생하지 않습니다. (비가 상 메소드에도 callvirt를 사용하므로 C #에서는이 작업을 수행 할 수 없습니다.)
Pop Catalin

7
예외는 완전히 잘못되었습니다. 호출 스택에서 발생할 수있는 모든 망할 예외를 포착해야한다면 빨리 실패 할 수 없습니다. 하지만 특정 호출과 그 결과 호출 스택에서 발생할 수있는 모든 예외를 훨씬 더 쉽게 식별 할 수 있기를 바랍니다.

3
@Will : 예외 처리는 Java와 .net 모두에서 엉뚱한 데, 사용 된 메커니즘은 다소 관련이 있지만 다소 직교하는 세 가지 개념을 밀접하게 연결하기 때문입니다. (1) 어떤 유형의 일이 잘못되었는지 (배열 경계 오류, I / O 타임 아웃 등); (2) 특정 코드가 결과적으로 조치를 취해야하는지 여부 (3) 어느 시점에서 문제가 "해결 된"것으로 간주되어야합니다. IEnumerable에서 읽은 데이터로 객체를 변경하는 루틴을 고려하십시오. 해당 IEnumerable 처리에서 예외가 발생하면 어떻게해야합니까?
supercat 2011

3

프레임 워크 V1의 SqlCommand에있는 .Parameters.Add () 메서드는 끔찍하게 설계되었습니다. 값 (int)이 0 인 매개 변수를 전달하면 오버로드 중 하나가 기본적으로 작동하지 않습니다. SqlCommand 클래스의 .Parameters.AddWithValue () 메서드


동의하지만 SqlCommand.Parameters.Add () 메서드를 의미한다고 생각합니다.
Matt Peterson

3
  1. ICollection<T>및의 하위 집합이 없습니다 IList<T>. 최소한 공변 읽기 전용 컬렉션 인터페이스 IListSource<out T>(열거 자, 인덱서 및 Count 포함)는 매우 유용했습니다.
  2. .NET은 약한 대리자를 지원하지 않습니다 . 해결 방법은 기껏해야 서투 르며 부분 신뢰에서는 리스너 측 해결 방법이 불가능합니다 (ReflectionPermission이 필요함).
  3. 일반적인 인터페이스 통합은 합리적이고 문제가없는 경우에도 금지 됩니다.
  4. C ++에서와 달리 공변 반환 형식 은 .NET에서 허용되지 않습니다.
  5. 두 값 유형이 같은지 비트 단위로 비교하는 것은 불가능합니다. 기능적 " 영구적 "데이터 구조 Transform(Sequence<T>, Func<T,T>)에서 함수가 동일한 값을 반환하는지 다른 값을 반환하는지 신속하게 결정하는 데 필요한 함수를 작성했습니다 . 함수가 인수의 대부분 / 전체를 수정하지 않으면 출력 시퀀스가 ​​입력 시퀀스의 일부 / 전체 메모리를 공유 할 수 있습니다. 값 유형 T를 비트 단위로 비교할 수없는 경우 훨씬 더 느린 비교를 사용해야하므로 성능이 크게 저하됩니다.
  6. .NET은 고성능 방식으로 애드혹 인터페이스 (예 : Go 또는 Rust에서 제공되는 인터페이스)를 지원하지 못하는 것 같습니다. 이러한 인터페이스를 사용 하면 클래스가 해당 인터페이스를 명시 적으로 구현하지 않더라도 List<T>가상 IListSource<U>(T : U) 으로 캐스팅 할 수 있습니다. 적어도이 있습니다 세 가지 다른 라이브러리 이 기능을 공급하는 (독립적으로 작성) (물론, 성능 단점으로는 - 완벽한 해결 방법은 할 수만 있으면 그것을 .NET의 결함으로 호출하는 공정을하지 않을 것이다).
  7. 기타 성능 문제 : IEnumerator에는 반복 당 두 개의 인터페이스 호출이 필요합니다. 일반 메서드 포인터 (IntPtr 크기의 열린 대리자) 또는 값 형식 대리자 (IntPtr * 2)는 사용할 수 없습니다. 고정 크기 배열 (임의 유형 T)은 클래스 내부에 포함될 수 없습니다. 없습니다 WeakReference<T>(쉽게 직접 작성할 수 있지만 내부적으로 캐스트를 사용합니다.)
  8. 동일한 대리자 유형이 호환되지 않는 것으로 간주된다는 사실 (암시 적 변환 없음)은 어떤 경우 (예 : Predicate<T>vs Func<T,bool>) 에 대해 성가신 일이었습니다 . .NET에서는 독립 DLL의 클래스가 동일한 인터페이스를 구현하는 것만으로는 충분하지 않기 때문에 컴포넌트 간의 결합을 완화하기 위해 인터페이스와 델리게이트에 대한 구조적 유형 지정 을 원합니다. 인터페이스를 정의하는 DLL입니다.
  9. DBNull.Valuenull동일한 목적을 똑같이 잘 수행했을 지라도 존재 합니다.
  10. C #에는 ?? = 연산자가 없습니다. 작성해야합니다 variable = variable ?? value. 실제로 C #에는 불필요하게 대칭이 부족한 곳이 몇 군데 있습니다. 예를 들어 if (x) y(); else z();(중괄호없이) 쓸 수는 있지만 try y(); finally z();.
  11. 스레드를 만들 때 자식 스레드가 부모 스레드에서 스레드 로컬 값을 상속하도록하는 것은 불가능합니다. BCL은이를 지원하지 않을뿐만 아니라 모든 스레드를 수동으로 생성하지 않는 한 직접 구현할 수 없습니다. 스레드 생성 이벤트가 있더라도 .NET 주어진 스레드 의 "부모"또는 "자식"알려줄 수 없습니다 .
  12. 서로 다른 데이터 유형에 대해 "Length"및 "Count"라는 두 가지 길이 속성이 있다는 사실은 사소한 문제입니다.
  13. 나는 WPF의 열악한 디자인에 대해 영원히 계속할 수 있으며 WCF (일부 시나리오에서는 매우 유용하지만)도 사마귀로 가득 차 있습니다. 일반적으로 많은 BCL의 최신 하위 라이브러리에 대한 부풀음, 직관적이지 않음 및 제한된 문서화로 인해 사용하기가 꺼려집니다. 많은 새로운 것들이 훨씬 더 간단하고, 작고, 사용하기 쉽고, 더 느슨하게 결합되고, 더 잘 문서화되고, 더 많은 사용 사례에 적용되고, 더 빠르고, 더 강력하게 입력되었을 수 있습니다.
  14. 나는 종종 속성 getter와 setter 사이의 불필요한 결합에 물렸다. 파생 클래스 또는 파생 인터페이스에서 기본 클래스 또는 기본 인터페이스에 getter 만 있으면 단순히 setter를 추가 할 수 없습니다. getter를 재정의하면 setter를 정의 할 수 없습니다. setter를 가상으로 정의 할 수 없지만 getter는 가상이 아닌 것으로 정의 할 수 있습니다.

및을 IList<T>사용하지만 의 하위 집합에 대해 동의합니다 . 당신의 다른 많은 것들은 저도 동의 할 것입니다. IReadableByIndex<out T>IAppendable<in T>
supercat

정말 긴 이름입니다. 어쩌면 우리는 타협 할 수 IListReader<T>) - 나는 "싱크"(쓰기 전용 인터페이스)의 반의어로 단어 "소스"를 사용합니다.
Qwertie

어쩌면 IListSource<in T>또는 IReadableList<out T>. 기본 인터페이스 유형에는 모든 파생물에 존재하지 않는 메서드가 포함되는 것이 가치가있을 수 있지만, 인터페이스를 다소 전문화하는 것이 좋은 경우가 많습니다. 예를 들어, IList<T>작동하거나 작동하지 않을 수있는 크기 조정 메소드를 포함 IResizableList<T>하는, 동일한 메소드를 구현하지만 작동을 보장하는를 가질 수 있습니다. 이러한 접근 방식은 필드가 변경 가능한 목록에 대한 유일한 현존 참조 또는 변경 불가능한 목록에 대한 공유 참조를 보유 할 수있는 경우에 유용 할 수 있습니다.
supercat

이 경우 목록의 내용을 변경하려는 코드는 변경 가능한 유형인지 여부를 확인하고 그렇지 않은 경우 변경 불가능한 목록과 동일한 항목을 포함하는 새 변경 가능한 인스턴스를 생성 한 다음 사용을 시작합니다. 코드가 변이 메소드를 사용하고 싶을 때마다 필드를 지속적으로 형변환해야한다면 그것은 짜증날 것입니다.
supercat 2012-07-18

@supercat C #은 인터페이스가 구현되었는지 확인하고 즉시 사용할 수있는 정말 쉬운 방법을 제공하지 않기 때문에 번거 롭습니다. MS는 더 쉽게하기 위해 언어 기능을 추가해야합니다. 내가 선호하는 기술은 바인딩 표현 if (rl:(list as IResizableList<T>) != null) rl.Add(...);이지만 다른 제안이 있습니다. 다양한 컬렉션 및 컬렉션 어댑터의 작성자로서 저를 짜증나게하는 것은 예외를 발생시키는 많은 더미 메서드를 작성하는 것입니다. 타입 안전 팬으로서 불법적 인 방법을 호출하는 것을 허용하고 싶지 않습니다. IntelliSense 팬인 경우 나열되는 것을보고 싶지 않습니다.
Qwertie

2

를 사용하는 경우 1.x에서 저를 쳤다 것은 있었다 System.Xml.XmlValidatingReaderValidationEventHandler의가 ValidationEventArgs가 기본 노출하지 않습니다 XmlSchemaException같은 모든 유용한 정보를 가지고있는 (내부 표시) linenumberposition. 대신 메시지 문자열 속성에서이를 구문 분석하거나 리플렉션을 사용하여 파싱해야합니다. 최종 사용자에게 좀 더 삭제 된 오류를 반환하려는 경우에는 좋지 않습니다.


1

한 열거 형의 값을 다른 열거 형에서 사용할 수 없다는 점이 마음에 들지 않습니다. 예를 들면 다음과 같습니다.

    enum Colors { white, blue, green, red, black, yellow }

    enum SpecialColors { Colors.blue, Colors.red, Colors.Yellow } 

2
하지만 이것은 말이되지 않습니다. typeof(Color)! = typeof(SpecialColors).
Kirk Woll

10
그것은 쉽게 할 충분하다 :enum SpecialColors { blue = Colors.blue, red = Colors.red, yellow = Colors.Yellow }
의 Trystan 스팽글

0

암시 적으로 형식화 된 변수는 IMO가 제대로 구현되지 않았습니다. Linq 표현식으로 작업 할 때만 실제로 사용해야한다는 것을 알고 있지만 로컬 범위 밖에서 선언 할 수 없다는 것은 성가신 일입니다.

MSDN에서 :

  • var는 동일한 명령문에서 지역 변수가 선언되고 초기화 될 때만 사용할 수 있습니다. 변수는 null, 메서드 그룹 또는 익명 함수로 초기화 될 수 없습니다.
  • var는 클래스 범위의 필드에 사용할 수 없습니다.
  • var를 사용하여 선언 된 변수는 초기화 표현식에서 사용할 수 없습니다. 즉,이 표현은 합법적입니다. int i = (i = 20); 그러나이 표현식은 컴파일 타임 오류를 생성합니다. var i = (i = 20);
  • 암시 적으로 형식이 지정된 여러 변수는 동일한 문에서 초기화 할 수 없습니다.
  • var라는 유형이 범위에있는 경우 var 키워드는 해당 유형 이름으로 확인되며 암시 적으로 유형이 지정된 지역 변수 선언의 일부로 처리되지 않습니다.

구현이 좋지 않다고 생각하는 이유는 var라고 부르지 만 변형이 되기에는 먼 길입니다. 전체 클래스 이름을 입력 할 필요가없는 간단한 구문입니다 (Linq와 함께 사용하는 경우 제외).


암시 적으로 형식화되지 않은 확실히 anon 형식 (새 {...}) (var)
Marc Gravell

내가 게시 한 내용을 다시 읽으면 잘못되었습니다. 난 암시 적으로 입력 된 변수를 의미 했어
lomaxx

1
Eric Lippert는 var를 메소드 외부에서 사용할 수없는 이유를 설명했습니다. 기본적으로 가능성의 블랙 박스를 생성하기 때문입니다. blogs.msdn.com/ericlippert/archive/2009/01/26/…
Guvante

1
var는 변형이 아닙니다! 속기 (특히 anon 유형)를위한 것입니다. 그것이 올 때 역동적으로 즐기십시오 ...
ShuggyCoUk
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.