5

I have an interface I, and I have just decided to deprecate method OldMethod (because it's badly named, because I want additional parameters, you name it) and advise users of my library to use NewMethod instead. Thus, I have extended I as follows:

Interface I
    <Obsolete("Use NewMethod instead.")>
    Sub OldMethod()
    Sub NewMethod()
End Interface

However, now all my classes implementing I get a compiler warning:

Class C
    Implements I

    ' The following line yields warning BC40000 
    Public Sub OldMethod() Implements I.OldMethod
        Throw New NotImplementedException()
    End Sub

    Public Sub NewMethod() Implements I.NewMethod
        Throw New NotImplementedException()
    End Sub
End Class

This doesn't make sense to me: To implement I (which, as a whole, is not obsolete), I need to implement OldMethod. The corresponding code in C# compiles perfectly fine and does not produce warnings:

interface I
{
    [Obsolete("Use NewMethod instead.")]
    void OldMethod();
    void NewMethod();
}

class Explicit : I
{
    public void NewMethod() { throw new NotImplementedException(); }
    public void OldMethod() { throw new NotImplementedException(); }
}

class Implicit : I
{
    void I.NewMethod() { throw new NotImplementedException(); }
    void I.OldMethod() { throw new NotImplementedException(); }
}

I know that I could just suppress the warning in VB, but, usually, a compiler warning indicates that you are doing something that should not be done in that way.

How can I implement an interface with an obsolete member in VB.NET without getting an obsolete warning?

Heinzi
  • 167,459
  • 57
  • 363
  • 519
  • 1
    Although cumbersome, you _can_ remove the warning by adding the same `Obsolete` attribute to the implementations. It's not ideal obviously – A Friend Oct 12 '18 at 15:13
  • @AFriend: Good point! Since C.OldMethod does not "inherit" the obsolete warning (and, thus, `myC.OldMethod()` won't show an obsolete warning, even though I'd want it to), this sounds like the correct solution (as intended by the language designers). If you make that an answer, I'll upvote! – Heinzi Oct 12 '18 at 15:20
  • What I know is that in a VB.Net project file `.vbproj` you have hard-coded warnings to treat as errors in the `` block and a ` ` block to exclude codes from warning. In a csproj, you have (possibly, it depends on the dev preferences) `MinimumRecommendedRules.ruleset` which may map to a different (managed) rule-set. It's possible that on the C# project, a code analysis + suppression has already been run. Or the rules are simply set differently (in `Options/Performace Tools/Rules`, where these rules are defined). – Jimi Oct 12 '18 at 15:30

1 Answers1

4

Fleshing out this answer from my comment.

The implementing class must implement the Obsolete member to fulfill the contract, but when the interface method is marked as Obsolete you must also mark the corresponding method as Obsolete to satisfy the compiler that the implementation of the Obsolete member is not to be used.

Public Interface I
    <Obsolete("Use NewMethod instead.")>
    Sub OldMethod() 
    Sub NewMethod()
End Interface

Public Class C
    Implements I

    <Obsolete("Use NewMethod instead.")>
    Public Sub OldMethod() Implements I.OldMethod ' No warning
        Throw New NotImplementedException()
    End Sub

    Public Sub NewMethod() Implements I.NewMethod
        Throw New NotImplementedException()
    End Sub
End Class

Although not entirely relevant for this particular question, whilst researching I found this blog post by Grant Winney explaining why it is a good idea to mark obsolete members on the interface member itself (as well as on the implementing member)

A Friend
  • 2,750
  • 2
  • 14
  • 23
  • I think the blog post misses the mark a little bit in its analysis. There are no warnings when you call through the interface because the static type of the object you are calling through is that of the interface, and the obsolete warning is based on the static type of the method that is called. – Craig Oct 12 '18 at 18:19