考慮這段代碼:
class Model {}
interface IApi1<T> where T: Model
{
T Create(T entity);
}
interface IApi2
{
T Create<T>(T entity) where T: Model;
}
class Foo {
IApi1<Model> api1;
IApi2 api2;
public T Do1<T>(T d) where T: Model => api1.Create(d); // ERROR
public T Do2<T>(T d) where T: Model => api2.Create(d); // WORKS
}
為什么標記為“錯誤”的行給了我"Cannot implicitly convert type 'Model' to 'T'"但看似相同的代碼在下一行有效?IApi2from的唯一區別IApi1是 where 條件從類宣告移動到方法宣告。為什么會有所作為?
我不是在尋找解決方案;我只是好奇為什么會有這種行為。
uj5u.com熱心網友回復:
讓我重命名一些型別引數,以便很容易看出我們在說什么:
interface IApi1<TApi1> where TApi1: Model
{
TApi1 Create(TApi1 entity);
}
interface IApi2
{
TApi2 Create<Api2T>(TApi2 entity) where TApi2: Model;
}
class Foo {
IApi1<Model> api1;
IApi2 api2;
public TDo1 Do1<TDo1>(TDo1 d) where TDo1: Model => api1.Create(d); // ERROR
public TDo2 Do2<TDo2>(T d) where TDo2: Model => api2.Create(d); // WORKS
}
當在型別上宣告型別引數時,例如在 的情況下IApi1,它在您撰寫型別時是“固定的”(或“確定的”)。也就是說,你寫的那一刻:
IApi1<Model> api1;
決定api1.Create接受 aModel并回傳 a Model。型別引數 ( TApi1) 替換為型別引數 ( Model)。
另一方面,如果在方法上宣告了型別引數,則在呼叫該方法之前它不是“固定的”。IApi2.Create可以接受任何TApi2并回傳相同的型別TApi2,其中TApi2是 a Model。只有當您呼叫 Create時,C# 才決定是什么TApi2。
Do1和都Do2宣告了型別引數,我稱它們為TDo1和TDo2。請注意,這些與型別引數TApi1和TApi2.
在Do1中,您嘗試回傳IApi1.Create回傳的內容。這是行不通的,因為IApi1.Create回傳 a Model,但Do1被宣告為 return TDo1,如果你還記得的話,它只會在呼叫者呼叫時確定Do1。的呼叫者Do1不妨傳遞另一個Model子類作為TDo1!的型別引數。
在Do2中,回傳IApi2.Create是可以的,因為IApi2.Create回傳的實際型別(即TApi2)在你呼叫它之前是不確定的。在這種情況下,推斷IApi2.Create將回傳TDo2,這反過來將在有人呼叫 時確定Do2。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/510439.html
標籤:C#仿制药编译器错误
上一篇:如何正確實作泛型結構
