[英]How to implement a dynamic generic type return method without casting at runtime in C#?
[英]C# method generic return type casting
我試圖在具有泛型返回類型的接口中創建一個方法,但我無法將泛型強制轉換為特定的類型/類。 但是,如果我將泛型放在接口上而不是方法上,我可以進行轉換。
換句話說,為什么這樣做
public class Rain {
public string propA {get;set;}
}
public interface IFoo<T> {
T foo();
}
public class Bar : IFoo<Rain> {
Rain foo() {
//...
return new Rain();
}
}
public bar = new Bar();
Rain rain = bar.foo();
但是不可能這樣做嗎?
public class Rain {
public string propA {get;set;}
}
public interface IFoo {
T foo<T>();
}
public class Bar : IFoo {
T foo<T>() {
//...
return new Rain();
}
}
public bar = new Bar();
Rain rain = bar.foo<Rain>();
有沒有其他方法(不使用Convert.ChangeType()
)?
第二個代碼片段無法編譯,因為Rain
不是T
在類中提供type參數時,沒有問題,因為該方法只能返回類聲明中已提供的類型。 換句話說 - T foo()
成為Rain foo
。
但是,當類型參數提供給方法時,該方法必須返回提供給它的任何類型 - 因此您不能返回除T
之外的任何類型。 換句話說,編譯器不能強制調用方法只使用foo<Rain>()
,但它可以強制foo
方法返回T
不同之處是:
// On this line you specify that the interface's generic type paramter 'T' is of type 'Rain',
// so the method implements the interface and returns a 'Rain'
public class Bar : IFoo<Rain> {
Rain foo() { // <= implements IFoo<Rain>.foo, where T = Rain so foo returns 'Rain'
return new Rain();
// In this version, the generic type parameter is declared on the method. It could be any type when the method is called, yet you always return a 'Rain'
public class Bar : IFoo {
T foo<T>() { // <= implements IFoo.foo<T> but the type of T is not specified yet
return new Rain();
這個“解決方案”取決於你的意圖。
Rain
,你為什么要在foo
方法上使用泛型參數呢? 當然,無論如何,你可以像這樣投出它:
T Foo<T>()
{
object result;
result = new Rain();
return (T)result; // note, this will throw at runtime if 'result' cannot be cast to 'T'
}
// call like this:
Bar.Foo<Rain>();
但我認為你的第一種方法IFoo<T>
非常有意義,為什么不使用呢?
UPDATE
根據您的評論:您還可以定義多個通用參數:
public interface IFoo<T1, T2>
{
T1 foo();
T2 foo2();
}
// implementation:
public class Bar : IFoo<Rain, Other>
{
Rain foo() { /* ... */ }
Other foo2() { /* ... */ }
}
如果你需要你的接口支持任意一組類,並且調用者確定使用哪些類,那么像這樣的東西是最通用的解決方案。
public class Bar : IFoo {
T foo<T>() {
if (typeof(T)==typeof(Rain))
return new Rain() as T;
if (typeof(T)==typeof(Snow))
return new Snow() as T;
Throw new ArgumentException("Not implemented for " + typeof(T).Name);
}
}
如果你所有的T都有一個共同的界面,那么你可以做的就是你感興趣的;
public class Snow : IWeather {...}
public class Rain: IWeather {...}
public class Bar : IFoo {
IWeather foo<T>() T : IWeather {
if (typeof(T)==typeof(Rain))
return new Rain();
if (typeof(T)==typeof(Snow))
return new Snow();
Throw new ArgumentException("Not implemented for " + typeof(T).Name);
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.