为什么这导致CS0695? [英] Why does this result in CS0695?

查看:143
本文介绍了为什么这导致CS0695?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

 公共接口PipelineElement<锡,出吹捧> 
{
IEnumerable的<&吹捧GT;润(IEnumerable的<锡GT;输入,动作<错误> errorReporter);
}

公共接口舞台
{
}

公共抽象类PipelineElementBase<锡,兜售> :PipelineElement<对象,对象> ;,
PipelineElement<锡,兜售>其中,锡:阶段,吹嘘:舞台
{
IEnumerable的<对象> PipelineElement<对象,对象> .RUN(IEnumerable的<对象>输入,动作<错误> errorReporter)
{
返回this.Run(input.Cast<锡GT;(),errorReporter).Cast<对象> ;();
}

公共抽象的IEnumerable<&吹捧GT;润(IEnumerable的<锡GT;输入,动作<错误> errorReporter);
}



对象没有按' ŧ实施舞台,因此既也不吹捧用不完为对象,对不对?那么,为什么编译器认为 PipelineElement<对象,对象> PipelineElement<锡,兜售> 可以成为一致?



编辑:是的,这是完全可以实现相同的通用接口多次:

 公共接口MyInterface的< A> {} 
公共MyClass类:MyInterface的<串>中MyInterface的< INT> {}


解决方案

从的 编译器错误CS0695




泛型类型'不能同时实现通用接口和通用
接口,因为它们可以统一为某种类型参数
替换。



在泛型类实现相同的通用接口的多个
参数时出现此错误,并且存在一个
型参数替换这将使两个接口
相同。为了避免这种错误,只实现一个接口,
或改变类型参数,以避免冲突。




您不能同时实现 PipelineElementBase<锡,兜售> PipelineElement<对象,对象> 接口,您的抽象类。



由于错误页说,你应该;




  • 实施只有一个这些或

  • 更改类型参数,以避免冲突。



从的 C#5.0语言规范




实现的接口13.4.2唯一



这是一个泛型类型声明实现的接口必须保持
是独一无二的所有可能的构造类型。如果没有这个规则,那就
无法确定正确的方法来调用某些
构造类型。例如,假设一个泛型类声明
被允许写成如下:




 接口I< T> 
{
无效F();
}
类X< U,V>:I< U> ;, I< V>
{
无效I< U> .F(){...}
无效I< V> .F(){...}
}




如果允许,就不可能确定哪个码了
执行在以下情况:




  I< INT> X =新的X< INT,INT>(); 
x.F();




要确定一个泛型类型声明的接口列表为
有效的,则执行以下步骤:




  • 设L是在一个通用类直接指定的接口列表中,结构或接口声明℃。


  • 添加到L接口的任何基本接口已经升。


  • 从L取下任何重复。


  • 如果从C创建的任何可能的构造类型会,经过类型参数代入L,导致两个接口在L达到
    相同,则C的声明是无效的。确定所有可能的
    构造类型时,约束
    声明不考虑。




在类声明的上方 X ,接口列表L由
I< U> I< V> 。该声明是无效的,因为任何建造
型与 U V 是相同的类型将导致这两个
接口是相同的类型



有可能在不同的继承
水平指定,以统一的接口

 接口I< T> 
{
无效F();
}
级基地< U>:I< U>
{
无效I< U> .F(){...}
}
类派生< U,V> ;:基地< U> ;, I< V> // OK
{
无效I< V> .F(){...}
}

这代码是有效的,即使派生< U,V> 同时实现了 I< U>
I< V> 。该代码



  I< INT> X =新的派生< INT,INT>(); 
x.F();



调用方法派生,因为派生< INT,INT> 有效
再器具 I< INT> (§13.4.6)。




[由SO编辑重点。]


public interface PipelineElement<in TIn, out TOut>
{
    IEnumerable<TOut> Run(IEnumerable<TIn> input, Action<Error> errorReporter);
}

public interface Stage
{
}

public abstract class PipelineElementBase<TIn, TOut> : PipelineElement<object, object>,
    PipelineElement<TIn, TOut> where TIn : Stage where TOut : Stage
{
    IEnumerable<object> PipelineElement<object, object>.Run(IEnumerable<object> input, Action<Error> errorReporter)
    {
        return this.Run(input.Cast<TIn>(), errorReporter).Cast<object>();
    }

    public abstract IEnumerable<TOut> Run(IEnumerable<TIn> input, Action<Error> errorReporter);
}

object doesn't implement Stage, therefore neither TIn nor TOut could ever be object, right? So why does the compiler think that PipelineElement<object, object> and PipelineElement<TIn, TOut> can become identical?

EDIT: Yes, it is perfectly possible to implement the same generic interface multiple times:

public interface MyInterface<A> { }
public class MyClass: MyInterface<string>, MyInterface<int> { }

解决方案

From Compiler Error CS0695

'generic type' cannot implement both 'generic interface' and 'generic interface' because they may unify for some type parameter substitutions.

This error occurs when a generic class implements more than one parameterization of the same generic interface, and there exists a type parameter substitution which would make the two interfaces identical. To avoid this error, implement only one of the interfaces, or change the type parameters to avoid the conflict.

You can't implement both PipelineElementBase<TIn, TOut> and PipelineElement<object, object> interfaces to your abstract class.

As the error page said, you should;

  • Implement only one of these or
  • Change the type parameters to avoid the conflict.

From C# 5.0 Language Specification

13.4.2 Uniqueness of implemented interfaces

The interfaces implemented by a generic type declaration must remain unique for all possible constructed types. Without this rule, it would be impossible to determine the correct method to call for certain constructed types. For example, suppose a generic class declaration were permitted to be written as follows:

interface I<T>
{
    void F();
}
class X<U,V>: I<U>, I<V>
{
    void I<U>.F() {...}
    void I<V>.F() {...}
}

Were this permitted, it would be impossible to determine which code to execute in the following case:

I<int> x = new X<int,int>();
x.F();

To determine if the interface list of a generic type declaration is valid, the following steps are performed:

  • Let L be the list of interfaces directly specified in a generic class, struct, or interface declaration C.

  • Add to L any base interfaces of the interfaces already in L.

  • Remove any duplicates from L.

  • If any possible constructed type created from C would, after type arguments are substituted into L, cause two interfaces in L to be identical, then the declaration of C is invalid. Constraint declarations are not considered when determining all possible constructed types.

In the class declaration X above, the interface list L consists of I<U> and I<V>. The declaration is invalid because any constructed type with U and V being the same type would cause these two interfaces to be identical types.

It is possible for interfaces specified at different inheritance levels to unify:

interface I<T>
{
  void F();
}
class Base<U>: I<U>
{
  void I<U>.F() {…}
}
class Derived<U,V>: Base<U>, I<V> // Ok
{
  void I<V>.F() {…}
}

This code is valid even though Derived<U,V> implements both I<U> and I<V>. The code

I<int> x = new Derived<int,int>();
x.F();

invokes the method in Derived, since Derived<int,int> effectively re-implements I<int>(§13.4.6).

[Emphasis by the SO editor.]

这篇关于为什么这导致CS0695?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆