일반적으로 C # 또는 .NET Framework의 가장 큰 디자인 결함은 무엇입니까?
예 : nullable이 아닌 문자열 유형이 없으며 IDataReader에서 값을 가져올 때 DBNull을 확인해야합니다.
답변
나는 이 게시물에 단호하게 동의합니다 (ToString이 부족한 사람들을 위해 클래스에 대한 사용자 정의 형식을 제공하는 디버거 속성이 있습니다).
위의 목록 위에 다음과 같은 합리적인 요청을 추가합니다.
- nullable 값 형식에 대한 보완으로서 nullable이 아닌 참조 형식,
- 구조체의 빈 생성자를 재정의 할 수 있습니다.
- 제네릭 타입 제약이 봉인 된 클래스를 지정하도록 허용
- 제약으로 사용될 때 임의의 생성자 서명을 요청한 다른 포스터에 동의합니다. 어디
T : new(string)
또는 어디T : new(string, int)
- 또한 빈 이벤트 목록과 동시 설정 모두에서 이벤트 수정에 대한 다른 포스터에 동의합니다 (후자는 까다 롭지 만).
- 연산자는 클래스의 정적 메소드가 아닌 확장 메소드로 정의되어야합니다 (또는 최소한 정적 메소드가 아닌).
- 인터페이스에 대한 정적 속성 및 메서드 허용 (Java에는이 기능이 있지만 C #에는 없습니다)
- 객체 이니셜 라이저에서 이벤트 초기화 허용 (현재 필드 및 속성 만 허용됨)
- “개체 이니셜 라이저”구문은 개체를 만들 때만 사용할 수있는 이유는 무엇입니까? 언제라도 사용 가능하게 만드는 것이 어떻습니까?
var e = new Foo(); e { Bar = baz };
- 2 차 열거 가능 동작 수정 ,
- 모든 컬렉션에는 반복을 위해 변경할 수없는 스냅 샷이 있어야합니다 (예 : 컬렉션을 변경하면 반복자가 무효화되지 않아야 함).
- 튜플은 추가하기 쉽지만 ”
Either<T>
” 와 같은 효율적인 폐쇄 형 대수 유형 은 그렇지 않습니다. 따라서 폐쇄 형 대수 유형을 선언하고 철저한 패턴 일치를 적용하는 방법을 좋아합니다 (기본적으로 방문자 패턴에 대한 일급 지원이지만 훨씬 더 효율적입니다. 따라서 열거 형을 취하고 철저한 패턴 일치 지원으로 확장하고 유효하지 않은 경우를 허용하지 마십시오. - 일반적으로 패턴 매칭에 대한 지원을 원하지만 최소한 객체 유형 테스트에 대해서는 지원합니다. 나는 또한 여기 다른 게시물에서 제안한 스위치 구문과 비슷합니다.
System.IO
같은 클래스Stream
가 다소 잘못 설계 되었다는 다른 게시물에 동의합니다 . 일부 구현이 필요한 인터페이스NotSupportedException
는 잘못된 디자인입니다.IList
현재보다 훨씬 간단해야합니다. 사실, 이것은 다음과 같은 많은 구체적인 컬렉션 인터페이스에 해당 될 수 있습니다ICollection
.- 예를 들어 IDictionary와 같은 예외가 너무 많은 메서드에서 발생합니다.
- Java에서 사용할 수있는 것보다 더 나은 확인 된 예외 형식을 선호합니다 (이 작업을 수행하는 방법에 대해서는 유형 및 효과 시스템에 대한 연구 참조).
- 일반적인 메서드 오버로드 해결에서 다양한 성가신 코너 케이스를 수정합니다. 예를 들어, 참조 유형에서 작동하는 두 개의 오버로드 된 확장 메소드를 제공하고 다른 하나는 nullable 구조체 유형에서 작동하고 유형 추론이 어떻게 좋아하는지 확인하십시오.
INotifyPropertyChanged
필드 이름을 문자열로 사용하는 인터페이스의 필드 및 멤버 이름을 안전하게 반영하는 방법을 제공 합니다.MemberExpression
, 즉 람다를 사용하는 확장 메서드를 사용하여이를 수행 할 수 있습니다 .() => Foo
하지만 그다지 효율적이지 않습니다.- 업데이트 : C # 6.0
nameof()
은 단일 멤버 이름에 대한 연산자를 추가 했지만 제네릭에서는 작동하지 않습니다 (nameof(T) == "T"
실제 형식 인수 이름 대신 수행해야 함typeof(T).Name
))- “경로”문자열을 가져올 수도 없습니다. , 예 :nameof(this.ComplexProperty.Value) == "Value"
가능한 응용 프로그램 제한.
- 업데이트 : C # 6.0
- 인터페이스에서 연산자를 허용하고 모든 핵심 번호 유형이 구현되도록합니다
IArithmetic
. 다른 유용한 공유 운영자 인터페이스도 가능합니다. - 객체 필드 / 속성을 변경하는 것을 더 어렵게 만들거나, 최소한 불변 필드에 주석을 달 수 있도록 허용하고 유형 검사기가이를 강제하도록합니다 (단지 chrissakes에서 getter 전용 속성으로 취급하면 어렵지 않습니다!). 사실 필드와 속성을 더 합리적으로 통합해야합니다. 둘 다 가지는 데는 의미가 없기 때문입니다. C # 3.0의 자동 속성은이 방향의 첫 번째 단계이지만 충분하지 않습니다.
- 업데이트 : C #에는
readonly
키워드가 있고 C # 6.0은 읽기 전용 자동 속성을 추가했지만 변경 불가능한 유형 및 값에 대한 실제 언어 지원만큼 엄격하지는 않습니다.
- 업데이트 : C #에는
- 선언 생성자를 단순화합니다. 나는 F #의 접근 방식을 좋아하지만, 클래스 이름 대신 단순히 “new”가 필요한 다른 게시물은 적어도 더 좋습니다.
지금은 충분하다고 생각합니다. 이것들은 지난주에 내가 만난 모든 자극입니다. 정말로 마음을 쏟으면 몇 시간 동안 계속할 수있을 것입니다. C # 4.0은 이미 명명 된, 선택적 및 기본 인수를 추가하고 있습니다.
이제 한 가지 비합리적인 요청 :
- C # / CLR이 형식 생성자 다형성을 지원할 수 있다면 정말 좋을 것 입니다. 제네릭보다 제네릭,
제발요? 🙂
답변
- 의
Reset()
메서드IEnumerator<T>
가 실수였습니다 (반복자 블록의 경우 언어 사양 에서 예외가 발생하도록 요구 합니다) - 배열을 반환하는 리플렉션 메서드는 Eric의 관점에서 실수 였습니다.
- 배열 공분산은 이상했고 여전히
- 업데이트 : .NET 4.0이 포함 된 C # 4.0은 일반 인터페이스에 공변 / 반 변성 지원을 추가했습니다 (
IEnumerable<out T>
및Func<in T, out TResult>
과 같지만 구체적인 형식 (예 🙂 은List<T>
아님).
- 업데이트 : .NET 4.0이 포함 된 C # 4.0은 일반 인터페이스에 공변 / 반 변성 지원을 추가했습니다 (
ApplicationException
오히려 호의적으로 떨어졌습니다-그게 실수였습니까?- 동기화 된 컬렉션-좋은 생각이지만 실제로는 유용하지는 않습니다. 일반적으로 여러 작업 (
Contains
, thenAdd
) 을 동기화해야 하므로 개별 작업을 동기화하는 컬렉션은 그다지 유용하지 않습니다.- 업데이트 : 유형 과는 , , , 등은 .NET 프레임 워크 4.0에 추가 된 – 공장의 위임을 받아 들일 방법이 공장은 키 당 한 번만 호출됩니다 보장하지 않습니다하지만.
System.Collections.Concurrent
TryAdd
GetOrAdd
TryRemove
- 업데이트 : 유형 과는 , , , 등은 .NET 프레임 워크 4.0에 추가 된 – 공장의 위임을 받아 들일 방법이 공장은 키 당 한 번만 호출됩니다 보장하지 않습니다하지만.
using
/lock
패턴을 더 많이 사용할 수 있습니다 .-아마도 재사용 가능한 (확장 가능한?) 구문을 공유 할 수 있습니다. 을 (를) 반환IDisposable
하고 사용하여 시뮬레이션 할 수using
있지만 더 명확 할 수 있습니다.- 반복자 블록 : 인수를 미리 확인하는 간단한 방법이 없습니다 (지연하지 않고). 물론 두 개의 연결 메서드를 작성할 수 있지만 그것은 추합니다.
- 더 간단한 불변성은 좋을 것입니다. C # 4.0은 약간 도움 이 되지만 충분하지는 않습니다.
- “이 ref-type 매개 변수는 null 일 수 없습니다.”지원은 없습니다. 그러나 계약 (4.0에서)이이 작업에 어느 정도 도움이됩니다. 그러나
Foo(SqlConnection! connection)
(null-check / 주입) 와 같은 구문은throw
좋을 것입니다 (대비int?
등)- 업데이트 : 이 문제는 C # 8.0에서 수정되었습니다 .
- 제네릭을 사용하는 연산자 및 기본이 아닌 생성자의 지원 부족 C # 4.0
dynamic
은을 사용 하여이 문제를 약간 해결 하거나 다음 과 같이 활성화 할 수 있습니다. - 확장 에서 while 외부 에서 선언되는 반복기 변수
foreach
, 즉 anon-methods / lambda가 반복 당 하나가 아닌 단일 변수를 캡처 함을 의미합니다 (스레딩 / 비동기 등으로 고통 스러움).- 업데이트 : 이것은 C # 5.0에서 수정되었습니다 .
답변
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에는 개발팀이 “좋아요, 우리는 충분히 가까웠습니다. 배송 해주세요!”라고 말한 것 같은 느낌이 들지 않습니다. 그러나 이것은 확실합니다.
답변
- 나는 Stream, StringWriter, StringReader, TextReader, TextWriter 클래스의 열렬한 팬이 아닙니다 … 무엇이 무엇인지 직관적이지 않습니다.
- IEnumerable.Reset이 반복기에 대한 예외를 발생시킵니다. 데이터 바인딩시 항상 재설정을 호출하는 타사 구성 요소가 있으며이를 사용하려면 먼저 목록으로 캐스팅해야합니다.
- XML Serializer에는 직렬화 된 IDictionary 요소가 있어야합니다.
- 나는 HttpWebRequest & FTP API에 대해 완전히 잊었다. 내 고통이 …. (Nicholas가 이것을 상기시켜 주셔서 감사합니다 🙂
편집
5. 또 다른 성가심은 System.Reflection.BindingFlags가 사용하는 방법에 따라 다른 용도로 사용된다는 것입니다. 예를 들어 FindFields에서 CreateInstance 또는 SetField는 무엇을 의미합니까? 이것은 그들이 혼란스러운이 열거 뒤에있는 의미를 오버로드 한 경우입니다.