尝试在扩展类型T上实现抽象泛型类时的C#编译错误

时间:2011-03-25 17:12:21

标签: c# generics .net-3.5

我正在使用泛型,觉得我已经深入了解并且想知道StackOverflow是否可以提供帮助?我认为使用我的代码的简化版本来解释我的问题要容易得多,而不是A类扩展B类的抽象例子。如果它过于简单,我会道歉。

我的C#(Windows Phone 7 .NET 3.5 )应用程序向Web服务发出请求,并使用填充从基类WebServiceResult派生的Result对象的XML响应。最初它触发了请求,解析了响应,然后调用方法将类型转换为预期的结果。我认为既然我们知道我们期待什么类型的结果,这是毫无意义的,并尝试使用泛型来实现这一目标。

// abstract class to do the raw http response handling
public abstract class WebServiceResultParser<T> where T : WebServiceResult {
    T result;
    public WebServiceResultParser(T result) {
        this.result = result;
    }

    protected abstract bool Parse(String response);
    private bool ParseHttpResponse(HttpWebResponse httpWebResponse){
        //some logic to get http response as string
        result.GetParser<T>().Parse(http_response_as_string);
        return true;
    }
}

// abstract class that models a webservice result
public abstract class WebServiceResult {
   protected internal abstract WebServiceResultParser<T> GetParser<T>() 
                                                where T : WebServiceResult;
}

实施“注册”网络服务请求

// knows how to parse the xml
public class RegistrationResultParser : WebServiceResultParser<RegistrationResult>{
    private RegistrationResult result;
    public RegistrationResultParser(RegistrationResult result)
        : base(result) {
            this.result = result;
    }

    protected override bool Parse(String response){
        //some logic to extract customer number
        result.CustomerNumber = customerNumber;
        return true;
    }
}
// stores the result
public class RegistrationResult : WebServiceResult {
    public String CustomerNumber { get; internal set; }

    protected internal override WebServiceResultParser<T> GetParser<T>() {
        return new RegistrationResultParser(this); // <--- Compiler error here
    }
}

编译错误说

  

无法将“RegistrationResultParser”类型隐式转换为“WebServiceResultParser<T>

这是我可以走的尽可能不绕圈而行。任何建议,进一步阅读或评论将不胜感激。

干杯, 麦金太尔。

2 个答案:

答案 0 :(得分:3)

编写代码的方式,无法保证GetParser<T>将返回WebServiceResultParser<RegistrationResult>(这是RegistrationResultParser继承的内容),因此无法编译。

我认为如果将方法更改为:

,它应该可以正常工作
protected internal override WebServiceResultParser<RegistrionResult> 
    GetParser<RegistrationResult>()
{
    return new RegistrationResultParser(this);
}

答案 1 :(得分:3)

现在的类结构不能编译,因为.NET框架在泛型上不是协变的或逆变的(好吧,它不是.NET 4.0之前的版本)。有关协方差和与泛型相关的逆转(包括如何在.NET 4.0中指定它们)的好文章可以在这里找到:http://msdn.microsoft.com/en-us/library/dd799517.aspx

但这有点让问题蒙上阴影,因为我不认为为你的类层次结构添加方差支持就是答案。

如果我正确理解您的意图 - 在RegistrationResult中,您试图说明您希望GetParser()方法返回WebResultParser<RegistrationResult>(而不是WebResultParser 1}}用于任何其他类型的WebServiceResult)。

要使它像这样工作,您需要进行以下更改(注释中的注释):

// update the constraint to match the new WebServiceResult definition
public abstract class WebServiceResultParser<T> where T : WebServiceResult<T>
{
    T result;
    public WebServiceResultParser(T result)
    {
        this.result = result;
    }

    protected abstract bool Parse(String response);
    private bool ParseHttpResponse(HttpWebResponse httpWebResponse)
    {
        //some logic to get http response as string
        var http_response_as_string = httpWebResponse.ToString();
        result.GetParser().Parse(http_response_as_string);
        return true;
    }
}

// move the type constraint from the GetParser() method to the class itself
public abstract class WebServiceResult<T> where T : WebServiceResult<T>
{
    protected internal abstract WebServiceResultParser<T> GetParser();
}

// no change
public class RegistrationResultParser : WebServiceResultParser<RegistrationResult>
{
    private RegistrationResult result;
    public RegistrationResultParser(RegistrationResult result)
        : base(result)
    {
        this.result = result;
    }

    protected override bool Parse(String response)
    {
        //some logic to extract customer number
        //result.CustomerNumber = customerNumber;
        return true;
    }
}

// explicitly specify the constraint on the base class (which is used to
// specify the GetParser() return type)
public class RegistrationResult : WebServiceResult<RegistrationResult>
{
    public String CustomerNumber { get; internal set; }

    protected internal override WebServiceResultParser<RegistrationResult> GetParser()
    {
        return new RegistrationResultParser(this);
    }
}

它之前是因为RegistrationResultParser仅来自WebServiceResultParser<RegistrationResult> ,而不是来自WebServiceResultParser<T>

整个A : B<A>确实看起来有点奇怪,但它确实实现了你想要做的事情。