일반적인 유형 질문으로부터의 추론
문제
나는 이것이 공개적으로 더 많은 공개라고 생각하지만 왜 C#을 내 ID 유형을 추론 할 수 없습니까?
public EntityT Get<EntityT>(IdT id) where EntityT : EntityObject<IdT>
다음과 같이 ID로 안내서가있는 정의 된 EntityObject :
public Foo : EntityObject<Guid>
다음과 같이 정의 된 추상 EntityObject 클래스에서 상속 :
public abstract class EntityObject<IdT>
{
public IdT id { get; set; }
}
Get 메소드의 사용법은 다음과 같습니다.
IRepository repository = new Repository();
var hydratedFoo = repository.Get<Foo>(someGuidId);
추가 설명을 제공하기 위해 편집.
해결책
당신이 그것들을 사용하는 방법이 아니라 두 개의 선언 만 주었다고 말하기는 어렵습니다. IDT는 다른 유형 매개 변수가 어딘가에 있습니까? (만약 그렇다면 TId
, 그것은 그것을 제안 할 것입니다 - 그러나 당신이 사용하고 있다는 사실은 EntityT
다른 유형 매개 변수의 경우 컨벤션과는 반대로 IdT
마찬가지로 ...)
이제 가정합니다 IdT
실제로입니다 Guid
귀하의 경우, 컴파일러는 어떻게 해야하는지 Foo
? 다른 유형이 도출 될 수 있습니다 EntityObject<Guid>
.
요컨대, 당신은 우리에게 확실히 말할 수있는 충분한 정보를 제공하지 않았지만, 당신은 기본적으로 컴파일러에 대해 불합리한 요구를하고있는 것처럼 들립니다.
편집 : 좋아, 여기에 당신이 가진 것에 대한 내 추측은 정상적인 명명 규칙을 사용합니다.
public interface IRepository
{
TEntity Get<TEntity, TId>(TId id) where TEntity : EntityObject<TId>
}
public abstract class EntityObject<TId>
{
public IdT id { get; set; }
}
public class Foo : EntityObject<Guid> {}
당신은하고 싶습니다 :
IRepository repository = GetRepositoryFromSomewhere();
Foo foo = repository.Get<Foo>(someGuid);
현재 해야하는 반면 :
Foo foo = repository.Get<Foo, Guid>(someGuid);
예, 컴파일러가 만들고 있습니다 아주 약간 필요한 것보다 더 어렵습니다. 언어를 더 단순하게 유지하고 유형 추론 규칙을 이해하기 쉽게하기 위해 6 개의 추가 캐릭터가 있습니다.
기본적으로 타입 추론은 전부 또는 아무것도 없습니다 - 모두 유형 매개 변수는 추론되거나 그 중 어느 것도 없습니다. 어떤 것이 지정되고 있는지, 그렇지 않은지 알아낼 필요가 없으므로 간단하게 유지합니다. 그것은 문제의 일부이며, 다른 부분은 방법의 유형 매개 변수에만 제약 조건을 표현할 수 있다는 것입니다.
class Repository<TEntity>
{
TEntity Get<TId>(TId id) where TEntity : EntityObject<TId>
}
그것이 제한적이기 때문입니다 TEntity
, 아니다 TId
. 다시 말하지만, 이런 종류의 것은 유형의 추론을 더 간단하게 만듭니다.
이제 당신 ~할 수 있었다 잠재적으로 쓰기 :
Foo foo = repository.Get(someGuid).For<Foo>();
적절한 Get
방법 및 추가 인터페이스. 나는 개인적으로 그냥 사용하는 것을 선호한다고 생각합니다 Get<Foo, Guid>
그렇지만.
다른 팁
선언과 같은 선언
public EntityT Get<EntityT>(IdT id) where EntityT : EntityObject<IdT>
IDT는 구체적인 유형이라는 요구를 요구합니다. IDT를 매개 변수화하려면 사용해야합니다.
public EntityT Get<EntityT, IdT>(IdT id) where EntityT : EntityObject<IdT>
그러나 그것은 아마도 당신이 원하는 것이 아닐 것입니다.
이것이 제가 일반 개체와 함께 일반적인 키 유형을 포기한 이유입니다. 나는 내 엔티티가 두 곳에 두 개를 뿌리지 않고 일반적인 키 유형을 갖도록하는 방법을 알 수 없었습니다. 이제 나는 정수 키에 정착했지만 (어쨌든 내가 가진 곳) 잘못 느껴집니다.
메소드 서명이 다음과 같이 보인 경우 :
public TEntity Get<TEntity, TId>(TId id) where TEntity : EntityObject<TId>
컴파일러는 작업 할 것이 있습니다 ...
그런 다음 다음과 같은 것을 호출합니다.
편집 (나는 틀렸다) : 제품 p = get (id);
Product p = Get<Product, Guid>(id);
Jon은 그의 게시물 위로이 답을 못 박 았으므로 내 구멍에서 닥치고 기어 올랐습니다.