【问题标题】:C# Compilation Error When Trying To Implement An Abstract Generic Class On An Extended Type T尝试在扩展类型 T 上实现抽象泛型类时出现 C# 编译错误
【发布时间】:2011-07-23 02:10:29
【问题描述】:

我正在使用泛型,但我觉得自己太过分了,想知道 StackOverflow 是否可以提供帮助?我认为使用我的代码的简化版本来解释我的问题会容易得多,而不是 A 类扩展 B 类的抽象示例等。如果它过于简单,我深表歉意。

我的 C# (Windows Phone 7 .NET 3.5) 应用程序触发对 Web 服务的请求,并使用 XML 响应填充从基类 WebServiceResult 派生的 Result 对象。最初它触发了请求,解析了响应,然后调用方法将 Result 类型转换为它所期望的结果。我认为既然我们知道我们期望什么类型的结果,这是没有意义的,并试图使用泛型来解决这个问题。

// 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&lt;T&gt;”

这是我能走的最远的地方,而不是绕圈子。任何建议、进一步阅读或 cmets 将不胜感激。

干杯, 阿拉斯代尔。

【问题讨论】:

    标签: c# generics .net-3.5


    【解决方案1】:

    按照您编写代码的方式,无法保证 GetParser&lt;T&gt; 将返回 WebServiceResultParser&lt;RegistrationResult&gt;(这是 RegistrationResultParser 继承自的内容),因此您无法编译。

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

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

    【讨论】:

    • 如果我进行此更改,编译会抱怨我没有正确实现抽象类。 “RegistrationResult”没有实现继承的抽象成员“WebServiceResult.GetDefaultParser()”
    • 刚刚看到您的编辑,它与@Rohit 相同,但不会像编译器所说的那样工作无法将类型'RegistrationResultParser'隐式转换为'WebServiceResultParser
    【解决方案2】:

    目前的类结构无法编译,因为 .NET 框架在泛型上不是协变或逆变的(嗯,它不是 .NET 4.0 之前的版本)。一篇关于泛型协变和逆变的好文章(包括如何在 .NET 4.0 中指定它们)可以在这里找到:http://msdn.microsoft.com/en-us/library/dd799517.aspx

    不过,这有点混淆了这个问题,因为我不认为向你的类层次结构添加差异支持是答案。

    如果我正确理解您的意图 - 在 RegistrationResult 中,您想说您希望 GetParser() 方法返回一个 WebResultParser&lt;RegistrationResult&gt;(而不是 WebResultParser 用于任何其他类型的WebServiceResult)。

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

    // 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&lt;RegistrationResult&gt; 仅,而不是从 WebServiceResultParser&lt;T&gt;

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

    【讨论】:

    • 谢谢,这是对泛型的惊人使用。我需要坐下来充分了解那里发生的事情,但它确实有效,并且它使派生类易于阅读和理解。
    猜你喜欢
    • 2017-06-15
    • 2015-09-07
    • 1970-01-01
    • 1970-01-01
    • 2015-10-22
    • 1970-01-01
    • 1970-01-01
    • 2020-05-14
    • 1970-01-01
    相关资源
    最近更新 更多