当T为IEnumerable <u> </u> </t>时,myClass <t>的隐式强制转换失败

时间:2012-09-10 01:57:33

标签: c# .net .net-3.5

我知道并且我认为我理解IEnumerables的(co/conta)variance问题。但是我认为以下代码不会受到影响。

[DataContract]
public class WcfResult<T>
{
    public WcfResult(T result)
    {
        Result = result;
    }

    public WcfResult(Exception error)
    {
        Error = error;
    }

    public static implicit operator WcfResult<T>(T rhs)
    {
        return new WcfResult<T>(rhs);
    }

    [DataMember]
    public T Result { get; set; }
    [DataMember]
    public Exception Error { get; set; }
}

这个类是模仿BackgroundWorker的RunWorkerCompletedEventArgs所以我可以从我的WCF服务返回错误而不会导致连接错误。

我的大多数代码都运行正常,所以我可以做这样的事情

public WcfResult<Client> AddOrUpdateClient(Client client)
{
    try
    {
        //AddOrUpdateClient returns "Client"
        return client.AddOrUpdateClient(LdapHelper);
    }
    catch (Exception e)
    {
        return new WcfResult<Client>(e);
    }
}

并且它工作正常,但是下面的代码会出错

public WcfResult<IEnumerable<Client>> GetClients(ClientSearcher clientSearcher)
{
    try
    {
        //GetClients returns "IEnumerable<Client>"
        return Client.GetClients(clientSearcher, LdapHelper, 100);
    }
    catch (Exception e)
    {
        return new WcfResult<IEnumerable<Client>>(e);
    }
}

错误在哪里

Cannot implicitly convert type 'System.Collections.Generic.IEnumerable<myNs.Client>'
to 'myNs.WcfResult<System.Collections.Generic.IEnumerable<myNs.Client>>'. An explicit
conversion exists (are you missing a cast?)

导致此错误发生的错误是什么?

1 个答案:

答案 0 :(得分:7)

啊,你被C#语言规范的一个不太明显的限制所挫败。

  

对于给定的源类型S和目标类型T,如果S或T可以为空   类型,让S 0 和T 0 引用它们的基础类型,否则S 0 和   T 0 分别等于S和T.允许使用类或结构   声明从源类型S到目标类型T的转换   如果满足以下所有条件:

     

·S 0 和T 0 是不同的类型。

     

·S 0 或T 0 是类或结构类型,其中   发生操作员声明。

     

· S 0 和T 0 都不是接口类型。

     

·不包括用户定义的转化,转化则不包括   从S到T或从T到S。

现在,似乎这不适用,因为您的隐式转换函数采用泛型参数,但此限制似乎同样适用于用作泛型参数的类型。我拿了你的例子并将IEnumerable更改为List(一个完整的类型,而不仅仅是一个接口)并且编译时没有错误。

总而言之,你只需要在WcfResult构造函数中包装任何返回接口类型的表达式,因为隐式转换将不可用。

return new WcfResult<IEnumerable<Client>>(Client.GetClients(clientSearcher, LdapHelper, 100));