我有一个方法可以返回实现通用接口的对象。它接受一个参数来确定实例化哪个类并返回实例化的对象。
public class PlayerRetriever
{
public static IPlayer<T> Retrieve(string SitePath)
{
if (SitePath == "Home") { return new Player1(); }
else { return new AnotherPlayer(); }
}
}
interface IPlayer<T>
{
void RunPlayer();
List<T> RetrievePlayersByMovie(string movie);
}
两者&#34; Player1&#34;和#34; AnotherPlayer&#34;实施IPlayer。
为什么我的方法会给我&#34;类型或命名空间&#39; T&#39;无法找到&#34; &#34; T&#34;下的错误在我的方法类型?
编写一种方法的正确方法是什么,其中返回类型是实现通用接口的对象?
答案 0 :(得分:6)
对于初学者,您的Retrieve
方法必须是通用的,如Retrieve<T>
。然后问题变成,当你调用它时,你需要指定T
的类型。如果您的Player1
和AnotherPlayer
未实现相同的IPlayer<T>
(意味着T
不同),那么您将指定什么作为通用的类型?
您可以做的是,创建一个IPlayer
非泛型接口,在其中将所有非泛型内容移动到其中,然后IPlayer<T>
从该接口继承,添加通用属性/方法。然后,您的方法可以返回非泛型IPlayer
。
答案 1 :(得分:4)
如果Player1
和AnotherPlayer
都实现了IPlayer
接口,则无需使用泛型。如果您传入要实例化的对象类型而不是字符串SitePath
,则可以使用反射来创建所需类型的对象。最简单的方法如下:
只需删除返回类型中的<T>
部分即可。
public class PlayerRetriever
{
public static IPlayer Retrieve(string SitePath)
{
if (SitePath == "Home") { return new Player1(); }
else { return new AnotherPlayer(); }
}
}
如果您需要访问特定于实现的属性,只需将其强制转换为原始类型:
AnotherPlayer castObject = (AnotherPlayer)returnedValue;
编辑 - 通用接口解决方案
由于您的IPlayer<T>
界面使用泛型,因此解决方案如下:
public IPlayer<T> Retrieve<T>(string SitePath)
{
if (SitePath == "Home") { return new Player1<T>(); }
else { return new AnotherPlayer<T>(); }
}
然后你会这样称呼它,但用string
类型代替代码所需的类型:
IPlayer<string> player = PlayerRetriever.Retrieve<string>("Home");
答案 2 :(得分:0)
在上面的代码中,您错过了PlayerRetriever
上的通用广告。它应该是PlayerRetriever<T>
。为了进一步提供你所拥有的东西,你可以对你的泛型加上约束,只接受一个实现IPlayer
的类型。约束为where T : IPlayer<T>
。如果您尝试传递任何未实现IPlayer
的内容,则无效。这应该更接近您正在寻找的内容并修复您的原始问题。
另外,如果要返回具体类,请考虑在反射中使用Activator来创建返回类型。那就是T myClass = Activator.CreateInstance<T>()
;
public class PlayerRetriever<T>
where T : IPlayer<T>
{
public static IPlayer<T> Retrieve(string SitePath)
{
if (SitePath == "Home") { return new Player1(); }
else { return new AnotherPlayer(); }
}
}
interface IPlayer<T>
{
void RunPlayer();
List<T> RetrievePlayersByMovie(string movie);
}