11

Consider the followng example - this uses an interface:

public interface IAlgorithm<TResult, TInput>
{
    TResult Compute(TInput input);
}

class A : IAlgorithm<int, byte[]>
{
    // Notice the use of params...not strictly what the interface specifies but it works.
    public int Compute(params byte[] input)
    {
        // no sane developer would go to this length to prove a point
        return input[0];
    }
}

A inst = new A();
Console.WriteLine(inst.Compute(1, 2, 3));
// 1

This example shows an interface, where it's method implementation (params byte[]) deos not exactly match the interface contract (byte[])...but it works!

Consider the followng example - this uses an abstract class:

public abstract class Algorithm<TResult, TInput>
{
    public abstract TResult Compute(TInput input);
}

class A : Algorithm<int, byte[]>
{
    // Notice the use of params...not strictly what the abstract class specifies, and it causes the compile to burst into tears!
    public override int Compute(params byte[] input)
    {
        // no sane developer would go to this length to prove a point
        return input[0];
    }
}

A inst = new A();
Console.WriteLine(inst.Compute(1, 2, 3));
//Compiler error: No overload for method 'Compute' takes 3 arguments

I want to know why this works for an interface, but not for an abstract class?

Matthew Layton
  • 39,871
  • 52
  • 185
  • 313
  • 2
    Can you change the type of `inst` in each example to match the abstract type: `IAlgorithm` and see what happens? It looks like the first version is using the `Compute` method from the class declaration directly and not via the interface. – Evil Dog Pie Jan 08 '15 at 15:44
  • @MikeofSST Very interesting. IAlgorithm inst = new A(); Console.WriteLine(inst.Compute(1, 2, 3)); naturally throws the error you'd expect :) – David L Jan 08 '15 at 15:52
  • 3
    Because the interface implementation satisfies the interface (i.e. it gives you a method that will receive a byte array) it is valid but the override of the abstract class is *not* valid because the signature of the overriding method doesn't match exactly. It works because the interface effectively only imposes a subset of what you can pass as an argument so you *can* use that method as a fully-working implementation of the one declared in the interface. – Ant P Jan 08 '15 at 15:54
  • I believe that this question is about difference between rules for matching interface implementation vs. virtual overrides matching - so while it is partially answered by http://stackoverflow.com/questions/15774529/changing-the-params-modifier-in-a-method-override thee is still second half about interface, so I don't think whole question is duplicate. – Alexei Levenkov Jan 08 '15 at 15:59
  • @AlexeiLevenkov Question is still a duplicate. It is slightly reworded. It can be interpreted as why the method first declared as a params works whilst it is ignored when overriding it. Answer is for abstract class method is not first declared in `A`, it is in `Algorithm` and thus method modifiers are taken from base class. Do note that Vs2014 with resharper gives a warning that params will be ignored when overriding, IMHO this question is a duplicate. – Sriram Sakthivel Jan 08 '15 at 16:08
  • @SriramSakthivel you are right. after re-reading question couple more times - yes, it is exact duplicate. In both cases classes themselves compile fine and really the only question here is why invocation of overriden method ignores `params`. Re-resolved as duplicate. – Alexei Levenkov Jan 08 '15 at 16:13
  • Side note: (not serious) strictly speaking it could have been downvoted into oblivion despite being well written interesting question as it does not provide *absolutely minimal* sample - knowing the answer there is nothing to do with generics at all. – Alexei Levenkov Jan 08 '15 at 16:32

0 Answers0