views:

536

answers:

8

I understand that interfaces are contracts and any changes (even additions) break any dependent code. However, I could have sworn I read something a while back that one of the recent .NET versions (3, 3.5??) added a new attribute that could be applied to new interface members. This attribute allowed versioning and/or making members optional. It would have been something like:

interface ITest
{
    void MethodOne();

    [InterfaceVersion(2)]
    void MethodTwo();
}

I have looked high and low for this but just can't seem to find it. I am wondering whether I simply misunderstood whatever I think I read and there is no such thing. Does someone have any insight?

+2  A: 

I know of no such attribute that allows an interface implementation to be partially implemented. You could work around this using an abstract class, however:

public abstract class Test
{
     public abstract void MethodOne();
     public virtual void MethodTwo() { }
}

This would allow the user to decide whether or not they want to override MethodTwo when inheriting from Test, while forcing the overriding of MethodOne.

David Morton
Sometimes, this solution, while surely not wrong, might break existing code for the lack of multiple inheritance.
phresnel
Yes, this is similar to what Kilhoffer said. I am aware of this but I usually avoid base classes unless my new class "is a" BaseClass (versus "has a" ISomething).
Nelson
+2  A: 

There's no such attribute in the .NET framework.

Jorge Córdoba
I specifically went through each attribute at http://msdn.microsoft.com/en-us/library/aa311259%28VS.71%29.aspx and didn't find one that stood out. I will have to agree with you for now.
Nelson
+8  A: 

I've not seen such an attribute, but I guess it's possible. This article on MSDN describes versioning through the use of the overrides and new keywords.

In short, C# is equipped with language features that allow derived classes to evolve and still maintain compatibility. This example shows a purely base-to-derived relationship, but the base would actually implement the interface you need to version. Having one interface require another (previous version) interface coupled with this method is quite useful as well.

Example of creating an interface that requires another:

public interface IMyInterface
{
  void FirstMethod();
}

public interface IMySecondInterface : IMyInterface
{
  void SecondMethod();
}

Example of using inheritance to maintain compatibility:

public class MyBase 
{
   public virtual string Meth1() 
   {
      return "MyBase-Meth1";
   }
   public virtual string Meth2() 
   {
      return "MyBase-Meth2";
   }
   public virtual string Meth3() 
   {
      return "MyBase-Meth3";
   }
}

class MyDerived : MyBase 
{
   // Overrides the virtual method Meth1 using the override keyword:
   public override string Meth1() 
   {
      return "MyDerived-Meth1";
   }
   // Explicitly hide the virtual method Meth2 using the new
   // keyword:
   public new string Meth2() 
   {
      return "MyDerived-Meth2";
   }
   // Because no keyword is specified in the following declaration
   // a warning will be issued to alert the programmer that 
   // the method hides the inherited member MyBase.Meth3():
   public string Meth3() 
   {
      return "MyDerived-Meth3";
   }

   public static void Main() 
   {
      MyDerived mD = new MyDerived();
      MyBase mB = (MyBase) mD;

      System.Console.WriteLine(mB.Meth1());
      System.Console.WriteLine(mB.Meth2());
      System.Console.WriteLine(mB.Meth3());
   }
}
Kilhoffer
I was aware of this method, but it's not using interfaces. I have received so many responses saying "no", that I must have misread it.
Nelson
The base class can implement the original interface
Kilhoffer
That's true. However, I think that it could be a bit confusing what your intentions are, even if it's perfectly valid. It still may be the best way in some circumstances (there is no "silver bullet" solution that is always the best solution).
Nelson
I completely agree with your last statement. It would have been nice if there was an explicit language feature to support the versioning of interfaces. An attribute as you suggested, perhaps.
Kilhoffer
Yeah, even though now I am not so convinced it would be "nice". See my comments on the original post. What is easier, specifying the attribute everywhere, or simply adding a number to the end of your interface (which doesn't require adding compiler features, etc.)?
Nelson
Just curious why you define two interfaces in your code example, IMyInterface, and IMySecondInterface, that are then never used in the code that follows.
BillW
They were really two separate points I was making. I've labeled them to reflect my intent. Thanks for pointing it out.
Kilhoffer
A: 

You may be thinking of partial methods (MSDN).

romkyns
No, but I didn't even know you could do that. Partial classes are used all over (designer vs user-generated code). I have learned about so many "edge cases/features" in C#/.NET reading through this forum!
Nelson
+9  A: 

You should create two interfaces:

interface ITest
{
    void MethodOne();
}

interface ITest2 : ITest
{
    void MethodTwo();
}

This would also make it clear which functionality requires which version of your interfaces, so that you don't have to check whether the class implementing the interface is implementing just one, or both, methods.

Lasse V. Karlsen
I have seen that done in the COM days. After a few years that can become a long list, but by then you may want to redesign your API anyway.
Nelson
The fact that COM has worked well for >15 years and almost that many versions of Windows, across hundreds of compilers for dozens of programming languages, should help convince you that the benefits outweigh any drawbacks.
Ben Voigt
+2  A: 

I recently was in the situation where the dictated lack of multiple inheritance forbid me to transform an existing interface into an abstract class, and found myself with an extending solution:

    interface IFoo {
            int RowCount();
    }

    static class _FooExtensions {
            public static bool HasAnyRows (this IFoo foo) {
                    return foo.RowCount() > 0;
            }
    }

That way you can provide a default version in case your abstract method can be defined in terms of the other functions.

phresnel
Right, this would be like a helper class. At first I thought you were referring to extension methods which in some situations would work well (LINQ, etc.). One thing that stood out, what does "this IFoo foo" do? I have used this to access instance members including jumping from one constructor to another, but I have never seen it used this way.
Nelson
@Nelson: that is an extension method. They aren't used just for LINQ.
Ben Voigt
Oops, my bad. I used an extension method once or twice, but didn't remember the full syntax. I understand it has many uses. It's still technically a "helper" class, but maintaining the OOP concepts without actually implementing an interface or deriving from a class. Very handy sometimes.
Nelson
A: 

You might have read something like

 interface ITest
{
    void MethodOne();

    [InterfaceVersion(2)]
    void MethodTwo();
}



[AttributeUsage(AttributeTargets.All)]
public class InterfaceVersion : System.Attribute
{
    public readonly int N;

    public InterfaceVersion(int n) 
    {
        this.N = n;
    }
}

But I don't think that could make implementation of MethodTwo optional.

EDIT:

I just found out by running the code that it really doesn't make implementation of MethodTwo optional.

TheMachineCharmer
Right, the compiler would not allow it to be optional, unless Microsoft specifically integrated (like [Obsolete()], etc.). Even then I am not sure how that would work and may be impossible to do.
Nelson
To your edit: yeah, it simply is a custom attribute that happens to have "Version" in the name. It could just as well be called "InterfaceNumber" and have exactly the same effect.
Nelson
+4  A: 

Are you perhaps thinking of the new "no pia" feature in C# 4? That is, we allow you to "link in" only the portions of an interface you actually use from a PIA, and then you can skip shipping the PIA to your customers. If you then do this several times in several different assemblies, the CLR does the work of figuring out that all those linked-in partial interfaces are logically the same type, and unifies them. That way you can pass objects that implement each flavour of the interface from one assembly to another and it all just works. However, the original interfaces that the "no pia" interfaces are created from has to be the same.

Eric Lippert
I don't think this was it, but sounds interesting. Do you by any chance have a link to some more information (examples, etc.)?
Nelson
@Nelson: http://blogs.msdn.com/samng/archive/2010/01/24/the-pain-of-deploying-primary-interop-assemblies.aspx
Eric Lippert