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

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

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



답변

나는 이 게시물에 단호하게 동의합니다 (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이 형식 생성자 다형성을 지원할 수 있다면 정말 좋을 것 입니다. 제네릭보다 제네릭,

제발요? 🙂


답변

  • 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가 반복 당 하나가 아닌 단일 변수를 캡처 함을 의미합니다 (스레딩 / 비동기 등으로 고통 스러움).


답변

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

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


답변

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

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

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


답변

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

여기서 T : new (U)

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

편집하다:

나는 이것을하고 싶다 :

public class A
{
    public A(string text)
    {

    }
}


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

}


답변

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

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

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