【问题标题】:Cannot implicitly convert type 'XXX' to 'T'无法将类型“XXX”隐式转换为“T”
【发布时间】:2016-08-15 21:21:26
【问题描述】:

我尝试使用工厂模式来获取使用泛型的类的实例。不知道我错过了下面的代码。

namespace ConsoleApplication1
{
    public interface IResult
    {
    }

    public class ResultA : IResult
    {
        public string P1 { get; set; }
    }

    public interface IService<T> where T : IResult
    {
        T DoWork();
    }

    public class ServiceA<T> : IService<T> where T : ResultA, IResult, new()
    {
        public T DoWork()
        {
            var t = new T();
            t.P1 = "value1";
            return t;
        }
    }

    public interface IFactory
    {
        T GetService<T>(string documentType) where T : IService<IResult>;
    }

    public class MyFactory : IFactory
    {
        public T GetService<T>(string documentType) where T : IService<IResult>
        {
            // based on documenet type I will be returning the instances of service here
            // im getting error at this line
            return new ServiceA<ResultA>();                }
    }

}

错误 1 ​​无法隐式转换类型 'ConsoleApplication1.ServiceA' 到 'T'

更新1
这也不起作用

public interface IFactory
{
    IService<IResult> GetService(string documentType);
}

public class MyFactory : IFactory
{
    public IService<IResult> GetService(string documentType)
    {
        return new ServiceA<ResultA>();
    }
}

【问题讨论】:

  • 我可以将ServiceFoo 传递给T(只要它继承IService&lt;IResult&gt;)并期望返回该类型,但您正试图显式返回ServiceA。看到问题了吗?
  • 能否提供代码?
  • 见下面的答案。你只是错过了一个演员。

标签: c# generics


【解决方案1】:

鉴于您知道在每个 IServiceA 中,T 都实现了 IResult,您无需将 Factory Generic 设为通用,只需将其绑定为返回 IService(如上一个答案所示)。但是,为了使代码编译,您需要在 MyFactory.GetService 中转换返回值,如下所示:

    ...
    public interface IFactory
    {
        IService<IResult> GetService(string documentType);
    }

    public class MyFactory : IFactory
    {
        public IService<IResult> GetService(string documentType)
        {
            //Cast needed to address the error...
            return (IService<IResult>) new ServiceA<ResultA>();
        }
    }

此代码应该与您尝试执行的代码相同,并且应该可以正确编译。

【讨论】:

  • 不知道为什么当 ServiceA 派生自 IService 时我需要强制转换它
  • 可能是因为编译器还没有编译你的“where”。
  • 嗯,在某种程度上,这是对编译器可能的限制。它与组合的通用变体类型有关(参见此处:msdn.microsoft.com/en-us/library/dd799517(v=vs.110).aspx)。问题是编译器可以知道 IService 可以从 ServiceA 强制转换,但是当你也像在 IService 中那样使用接口作为参数时,它不能保证它是类型安全的,因此它要求您明确地转换它以确保您知道该类可以安全地转换。
  • 这里有更多相关信息:blogs.msdn.microsoft.com/csharpfaq/2010/02/16/…。具体来说:“如果你实现了一个变体泛型接口,那么实现类仍然是不变的。类和结构在 C# 4.0 中不支持变体。”所以以下内容无法编译: // List 实现协变接口 // IEnumerable。但是类是不变的。 List list = new List(); // 这里是编译器错误。
【解决方案2】:

你有 T 的每个地方,用 IResult 替换它

public interface IService<IResult>
{
    IResult DoWork();
}

public class ServiceA<IResult> : IService<IResult> {}



public interface IFactory
{
    IResult GetService(string documentType);
}

【讨论】:

    【解决方案3】:

    你需要转换你的结果。 我还认为编译器需要编译你的“where”子句,这似乎是一个 IEnumerable(根据我的经验)。

    【讨论】:

      猜你喜欢
      • 2019-12-02
      • 1970-01-01
      • 2019-12-12
      • 2011-12-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多