2008-09-05 1 views
44

C#을 제네릭 형식 매개 변수를 지정할 필요가 없습니다 :C#이 클래스 생성자에서 묵시적 제네릭 형식을 지원하지 않는 이유는 무엇입니까? 컴파일러는 예를 들어, 그것을 추론 할 수있는 경우

List<int> myInts = new List<int> {0,1,1, 
    2,3,5,8,13,21,34,55,89,144,233,377, 
    610,987,1597,2584,4181,6765}; 

//this statement is clunky 
List<string> myStrings = myInts. 
    Select<int,string>(i => i.ToString()). 
    ToList<string>(); 

//the type is inferred from the lambda expression 
//the compiler knows that it's taking an int and 
//returning a string 
List<string> myStrings = myInts. 
    Select(i => i.ToString()). 
    ToList(); 

이것은 당신이 형식 매개 변수가 (어떻게 될지 모르는 익명 형식에 필요 인텔리 센스에서는 컴파일러에 의해 추가 되었기 때문에 'a으로 나타납니다.

클래스 수준의 형식 매개 변수는이 작업을 수행하지 않습니다

//sample generic class 
public class GenericDemo<T> 
{ 
    public GenericDemo (T value) 
    { 
     GenericTypedProperty = value; 
    } 

    public T GenericTypedProperty {get; set;} 
} 

//why can't I do: 
int anIntValue = 4181; 
var item = new GenericDemo(anIntValue); //type inference fails 

//however I can create a wrapper like this: 
public static GenericDemo<T> Create<T> (T value) 
{ 
    return new GenericDemo<T> (value); 
} 

//then this works - type inference on the method compiles 
var item = Create(anIntValue); 

이유는 무엇입니까이 클래스 수준의 일반적인 형식 유추하지 C#을 지원합니까?

+0

왜이 질문에 대해 [C# 생성자가 유추 할 수없는 이유는 무엇입니까?] (http://stackoverflow.com/questions/3570167) 그 질문이 2 년 더 최근입니까? 확실히 그게 복제품이야? – Keith

+0

나는 다른 질문이 더 간결하다고 생각하며, 더 나은 대답을 가지고있다. – Sam

+0

@Sam - 예, 에릭 리 퍼트의 대답은 권위가 있지만 어느 쪽의 질문도 닫지 않아야한다고 생각합니다. – Keith

답변

25

사실, 귀하의 질문은 나쁘지 않습니다. 지난 몇 년 동안 제네릭 프로그래밍 언어를 사용 해왔다. 실제로 개발하지는 않았지만 (아마도 그렇게되지는 않겠지 만) 제네릭 형식 유추에 대해 많이 생각해 왔으며, 나의 최우선 과제 중 하나는 제네릭 형식을 지정하지 않고도 항상 클래스를 생성 할 수있었습니다.

C#에는이 작업을 가능하게하는 일련의 규칙이 없습니다. 나는 개발자들이 이것을 포함하는 것을 결코 보지 못했다고 생각한다. 사실, 다음 코드는 당신의 제안에 매우 가깝고 문제를 해결할 것입니다. 모든 C# 요구 사항은 추가 구문 지원입니다.

class Foo<T> { 
    public Foo(T x) { … } 
} 

// Notice: non-generic class overload. Possible in C#! 
class Foo { 
    public static Foo<T> ctor<T>(T x) { return new Foo<T>(x); } 
} 

var x = Foo.ctor(42); 

이 코드가 실제로 작동하기 때문에 문제는 의미론이 아니라 단순히 지원이 부족한 것으로 나타났습니다. 나는 나의 이전 게시를 되찾아야한다고 생각한다. ;-)

11

왜이 클래스 수준 제네릭 형식 추론을 지원하지 않습니까?

일반적으로 모호하기 때문에. 반대로 형식 유추는 함수 호출 (모든 형식이 인수에 나타나는 경우)에 대해서는 사소한 것입니다. 그러나 생성자 호출 (논의를 위해 glorified 함수)의 경우 컴파일러는 동시에 여러 수준을 해결해야합니다. 한 레벨은 클래스 레벨이고 다른 하나는 생성자 인수 레벨입니다. 나는 이것이 알고리즘 적으로 중요하지 않다는 것을 믿는다. 직관적으로, NP 완성이라고 할 수 있습니다.

해상도가 불가능하다 극단적 인 경우를 설명하기 위해, 컴파일러는 무엇을해야 다음 클래스를 상상 말해 :

class Foo<T> { 
    public Foo<U>(U x) { } 
} 

var x = new Foo(1); 
+0

Konrad의 질문이 공식화 된 방식에서 "int"유형이 단순히 "new Foo (1)"에서 유추 될 수 없다는 것을 이미 알고 있습니다. 그러나 그 누구도 나에게 설명 할 수 없습니까? 내 말은, "var x = 1"이라고 말하면 int로 끝납니다. 그래서이 예제와 어떻게 다른가요? –

+0

나는 생각하지 않는다 * 왜냐하면 그들은 일반적으로 모호하기 때문에 * 아주 좋은 이유이다; 제네릭 메서드도 동일한 서명이있는 비 제너릭 메서드가있는 경우 모호합니다. – Sam

+0

@Sam 전적으로 동의합니다. 그러므로 제 다른 (받아 들인) 대답을보십시오. 그러나, 나는 이것이 C#에 존재하지 않는 원래의 이유라고 믿는다. 이 질문은 Stack Overflow가 답변에 대해보다 엄격한 규칙을 적용하기 전에 작성된 주석이 실제로 구현되기 전에 실제로 작성된 것입니다. 결과적으로이 전체 스레드는 토론이었습니다. 이 답변을 삭제하지 않은 유일한 이유는 나머지 답변이 여기 혼란스러워지기 때문입니다. –

2

감사 콘라드, 즉 좋은 반응 (+1), 그러나 단지 확장 그 위에.

은의 그 C 번호가 명시 적으로 생성자 함수를 가지고 척하자

//your example 
var x = new Foo(1); 

//becomes 
var x = Foo.ctor(1); 

//your problem is valid because this would be 
var x = Foo<T>.ctor<int>(1); 
//and T can't be inferred 

첫 번째 생성자는 추론 할 수 없음을 확실히 맞다.

지금은 (는 대체 유형)에 다시 생성자를 추가하는 경우의 우리가 모호한 전화를 가지고, 클래스 물론

class Foo<T> 
{ 
    //<T> can't mean anything else in this context 
    public Foo(T x) { } 
} 

//this would now throw an exception unless the 
//typeparam matches the parameter 
var x = Foo<int>.ctor(1); 

//so why wouldn't this work? 
var x = Foo.ctor(1); 

으로 돌아 가자 - 정확히 일반 메서드 오버로드가없는 경우 등 해결되다.

관련 문제