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

试图在扩展类型T上实现抽象泛型类时出现C#编译错误,c#,generics,.net-3.5,C#,Generics,.net 3.5,我正在使用泛型,我觉得我已经陷入了太深的头脑中,想知道StackOverflow是否能帮上忙?我认为用我的代码的简化版本来解释我的问题要容易得多,而不是用一个抽象的类a扩展类B等等的例子。如果过于简单,我很抱歉 我的C#(Windows Phone 7.NET 3.5)应用程序向Web服务发出请求,并使用填充从基类WebServiceResult派生的结果对象的XML响应。最初它启动请求,解析响应,然后调用方法将结果类型转换为它期望的结果。我认为,既然我们知道我们期望的结果是什么类型的,这是毫无

我正在使用泛型,我觉得我已经陷入了太深的头脑中,想知道StackOverflow是否能帮上忙?我认为用我的代码的简化版本来解释我的问题要容易得多,而不是用一个抽象的类a扩展类B等等的例子。如果过于简单,我很抱歉

我的C#(Windows Phone 7.NET 3.5)应用程序向Web服务发出请求,并使用填充从基类WebServiceResult派生的结果对象的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;
}
//执行原始http响应处理的抽象类
公共抽象类WebServiceResultParser,其中T:WebServiceResult{
T结果;
公共WebServiceResultParser(T结果){
this.result=结果;
}
受保护的抽象布尔解析(字符串响应);
私有布尔解析HttpResponse(HttpWebResponse HttpWebResponse){
//将http响应作为字符串获取的一些逻辑
result.GetParser().Parse(http_响应作为_字符串);
返回true;
}
}
//为webservice结果建模的抽象类
公共抽象类WebServiceResult{
受保护的内部抽象WebServiceResultParser GetParser()
其中T:webservicesult;
}
“注册”webservice请求的实现

// 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
    }
}
//知道如何解析xml
公共类注册结果解析器:WebServiceResultParser{
私人注册结果;
公共注册结果服务器(注册结果)
:基准(结果){
this.result=结果;
}
受保护的覆盖布尔解析(字符串响应){
//提取客户号的一些逻辑
result.CustomerNumber=CustomerNumber;
返回true;
}
}
//存储结果
公共类注册结果:WebServiceResult{
公共字符串CustomerNumber{get;internal set;}
受保护的内部重写WebServiceResultParser GetParser(){

返回新的RegistrationResultParser(this);//按照编写代码的方式,
GetParser
无法保证将返回
WebServiceResultParser
(这是RegistrationResultParser继承的内容),因此无法编译

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

protected internal override WebServiceResultParser<RegistrionResult> 
    GetParser<RegistrationResult>()
{
    return new RegistrationResultParser(this);
}
受保护的内部重写WebServiceResultParser
GetParser()
{
返回新的RegistrationResultPasser(此);
}

当前的类结构无法编译,因为.NET framework在泛型上不是协变或逆变的(好吧,它不是.NET 4.0之前的版本)。在这里可以找到一篇关于泛型的协变和逆变的好文章(包括如何在.NET 4.0中指定它们):

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

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

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

//更新约束以匹配新的WebServiceResult定义
公共抽象类WebServiceResultParser,其中T:WebServiceResult
{
T结果;
公共WebServiceResultParser(T结果)
{
this.result=结果;
}
受保护的抽象布尔解析(字符串响应);
私有布尔解析HttpResponse(HttpWebResponse HttpWebResponse)
{
//将http响应作为字符串获取的一些逻辑
var http_response_as_string=httpWebResponse.ToString();
result.GetParser().Parse(http_响应作为_字符串);
返回true;
}
}
//将类型约束从GetParser()方法移动到类本身
公共抽象类WebServiceResult,其中T:WebServiceResult
{
受保护的内部抽象WebServiceResultParser GetParser();
}
//不变
公共类注册结果解析器:WebServiceResultParser
{
私人注册结果;
公共注册结果服务器(注册结果)
:基准(结果)
{
this.result=结果;
}
受保护的覆盖布尔解析(字符串响应)
{
//提取客户号的一些逻辑
//result.CustomerNumber=CustomerNumber;
返回true;
}
}
//显式指定基类上的约束(用于
//指定GetParser()返回类型)
公共类注册结果:WebServiceResult
{
公共字符串CustomerNumber{get;internal set;}
受保护的内部重写WebServiceResultParser GetParser()
{
返回新的RegistrationResultPasser(此);
}
}
它以前是中断的,因为
RegistrationResultParser
仅从
WebServiceResultParser
继承,而不是从
WebServiceResultParser


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

如果我做了此更改,编译器会抱怨我没有正确实现抽象类。'RegistrationResult'没有实现继承的抽象成员'WebServiceResult.GetDefaultParser()“刚刚看到您的编辑,它与@Rohit相同,但不能像编译器所说的那样工作。无法将类型“RegistrationResultParser”隐式转换为“WebServiceResultParserThank you”,这是泛型的一个惊人用法。我需要坐下来充分理解它的作用
// 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);
    }
}