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

时间:2016-06-15 11:26:47

标签: c# compiler-warnings

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

interface Foo : IEnumerable<Bar>{

    int SomethingNonObsolete{
         get;
    }

}

在上面的例子中,我希望使用已实现的IEnumerable的迭代器导致编译器 - 过时警告,而使用接口本身或使用SomethingNonObsolete - 属性不会导致这样的警告。

以下代码应该指向编译器过时的警告

foreach(var bar in myFooImplementingInstance){

以下代码不应该指向编译器过时的警告

myFooImplementingInstance.SomethingNonObsolete.ToString()

更新
因为有很多答案,但每个答案只涉及问题的一部分,这里是摘要和最终陈述:

最后,由于LINQ,技术上不可能。

如果有人会使用它,正如Panda在他的回答中所说,这对于课程来说很容易。宣布调查员已经过时,你的罚款。

[Obsolete]
IEnumerator<Bar> GetEnumerator()
[Obsolete]
IEnumerator IEnumerable.GetEnumerator()

对于接口,它可以以类似的方式完成,如Bozhidar在评论中评论。使用new-keyword声明枚举器并将其标记为过时。

[Obsolete]
new IEnumerator<ITabularDataRow> GetEnumerator();

然而,虽然这两个版本一般都是他们应该做的,但是在使用LINQ时它们都会破坏。 因此,答案似乎是全面的方式是不可能的,并且这在大多数情况下是好的(参见MDeSchaepmeester的答案和评论)。

4 个答案:

答案 0 :(得分:4)

在实施界面时,如下所示在Obsolete方法中添加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();
    }
}

结果:

var c = new MyClass();

// Flagged as obsolete
foreach (var blah in c)
{

}

// Not flagged as obsolete
var s = c.SomethingNonObsolete;

答案 1 :(得分:2)

您可以使用ObsoleteAttribute将成员标记为已过时。将它添加到每个过时的方法中,您将收到警告(或错误,具体取决于参数)。但是,这意味着您需要指定所有成员 - 除了实现Foo的实例之外,这在您的情况下是不可能的。您唯一的另一个选择是将整个界面标记为过时,并将其替换为Foo2 - 事实上,这可能是解决此问题的最佳方式。

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

答案 2 :(得分:0)

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

Obsolete主要用于提供替代,例如通过XML文档(例如,如果您使用SomethingNotObsolete标记Obsolete并说use SomethingNew instead

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

我用一句话说的是Obsolete在你的情况下在语义上是不正确的。

答案 3 :(得分:0)

您可以创建一个新界面。现在,在新界面中,您不会继承IEnumerable并创建原始界面Obsolete。现在,无论谁使用foreach(Foo f in myFooImplementingInstance)都会收到你过时的消息。理想情况下,您还应添加一个提示,应该使用新接口。基本的想法是你的界面有一个唯一的目的。改变其继承链或类似方法将以极不可预测的方式破坏目的。因此,您应该创建一个提供新要求的新界面。

但是我同意@MDeSchaepmeester这是一个重要的重组,应该有详细记录。这样做将大量重新构建消费者代码,因此应该谨慎规划和实施。