C# 将接口或类的实现IEnumerable声明为已过时

C# 将接口或类的实现IEnumerable声明为已过时,c#,compiler-warnings,C#,Compiler Warnings,是否可以将接口或类的派生或实现的IEnumerable部分声明为已过时,而类或接口的其余部分仍然是当前的?我该如何申报 interface Foo : IEnumerable<Bar>{ int SomethingNonObsolete{ get; } } 以下代码不应导致编译器过时警告 foreach(var bar in myFooImplementingInstance){ myFooImplementingInstance.Somet

是否可以将接口或类的派生或实现的IEnumerable部分声明为已过时,而类或接口的其余部分仍然是当前的?我该如何申报

interface Foo : IEnumerable<Bar>{

    int SomethingNonObsolete{
         get;
    }

}
以下代码不应导致编译器过时警告

foreach(var bar in myFooImplementingInstance){
myFooImplementingInstance.SomethingNonObsolete.ToString()
更新
因为有很多答案,但每个答案都只涉及问题的一部分,这里有一个总结和一个最终声明:

最后,这在技术上是不可能的,因为LINQ

如果一个人无论如何都会使用它,就像熊猫在他的回答中所显示的那样,这对于课堂来说是很容易做到的。将枚举数声明为已过时,并罚款

[Obsolete]
IEnumerator<Bar> GetEnumerator()
[Obsolete]
IEnumerator IEnumerable.GetEnumerator()
[过时]
IEnumerator GetEnumerator()
[过时]
IEnumerator IEnumerable.GetEnumerator()
对于接口,可以用类似的方式完成,如注释中的Bozhidar注释。用new关键字声明枚举数并将其标记为已过时

[Obsolete]
new IEnumerator<ITabularDataRow> GetEnumerator();
[过时]
新的IEnumerator GetEnumerator();
然而,虽然这两个版本通常都做它们应该做的事情,但它们在使用LINQ时都会中断。
因此,答案似乎是,这不可能以全面的方式实现,而且在大多数情况下,这是好的(参见MDeSchaepmeester的答案和评论)

您可以使用
obsoletateAttribute
将成员标记为已过时。将它添加到每个过时的方法中,您将得到警告(或错误,具体取决于参数)。但是,这意味着您需要指定所有成员—在您的情况下,除了在实现
Foo
的实例上,这是不可能的。您唯一的其他选择是将整个接口标记为过时,并用
Foo2
替换它-事实上,这可能是最好的方法


另外,请注意,这将只处理直接调用。编译器无法知道
((IEnumerable)yourFooInstance).GetEnumerator()
应该过时。

在实现接口时,在
GetEnumerator
方法上添加
过时的属性(如下所示)会导致您的期望:

[Obsolete]
new IEnumerator<ITabularDataRow> GetEnumerator();
public class MyClass : Foo
{
    public int SomethingNonObsolete
    {
        get
        {
            throw new NotImplementedException();
        }
    }

    [Obsolete]
    public IEnumerator<Bar> GetEnumerator()
    {
        throw new NotImplementedException();
    }

    [Obsolete]
    IEnumerator IEnumerable.GetEnumerator()
    {
        throw new NotImplementedException();
    }
}

这是一个有趣的情况,但您将要做的是对API进行相当重要的更改

过时
主要在您可以提供替代方案时使用,例如通过XML文档(例如,如果您使用
过时
标记
某物不过时
,并说
改用某物新

您将要对API进行的更改将需要使用者重新构造代码,而不是简单地替换方法调用。因此,您应该(理想情况下)将此保留给API的主要版本,并为使用者记录迁移路径


我在一句话中说的是,
过时的
在您的情况下在语义上是不正确的。

您可以创建一个新接口。现在在您的新接口中,您不会继承
IEnumerable
,并使原始接口
过时
。现在,无论谁使用
foreach(在MyFoooImplementingInstance中为foof)
获取您的过时消息。理想情况下,您还应该添加一个提示,说明应该使用新接口。基本思想是,您的接口只有一个用途。更改其继承链或类似内容将以一种高度不可预测的方式破坏用途。因此,您应该创建一个新接口,以提供新要求ts


但是,我同意@MDeSchaepmeester的观点,这是一个重大的重组,应该有很好的文档记录。这样做会对消费者代码进行大规模重组,因此应该谨慎地进行规划和实施。

如果我理解正确,在接口上是不可能的,但是如果我将具体类的迭代器归为属性的话,foreach调用将被编译器警告修饰?@HCL是的,因为
foreach
欺骗并且根本不使用
IEnumerable
接口。另一方面,LINQ方法确实使用
IEnumerable`1
,因此它们根本不会“看到”您过时的属性。隐藏
GetEnumerator()是完全合法的
并在接口定义中用属性标记它。使用
new
关键字如下:
new IEnumerator GetEnumerator()
那么您基本上想从API中删除接口?为什么不创建一个不实现接口的新类?不,我想从接口中删除IEnumerable,但我目前无法这样做,因为许多应用程序都依赖于接口。我想防止开发人员在新的API中对IEnumerable使用foreache以便将来更容易删除,而且我们没有更多的引用。有一种方法可以通过您问题中的确切代码示例来实现这一点,但是对
IEnumerable
IEnumerable
的简单转换不会被标记为过时,也不会对其进行枚举。总之,这不会解决所有问题。@HCL如果“许多应用程序依赖于该接口”,那么将其标记为过时并不能解决问题。您看到的是公共API中的巨大变化,您希望将其记录为比将某些内容标记为过时要好一点的内容。不确定这是否属实。有其他方法可以在工具栏上进行迭代(在返回Ienumerable的属性上)。Ienumerable的实现是附加的,只是为了方便。但是,它表明,它的存在并不是那么令人愉快。您不只是为了方便而在.NET中实现
Ienumerable
。这是一种标准的通信方式,可以对某些内容进行迭代。如果您无法在任何应可枚举的内容上实现它,那么您就做错了。感谢您的指导,问题仍然存在。@HCL,我的答案也仍然存在。有一个原因是.NET framework不提供标记扩展为