Nested contracts for generic interfaces - c#

I can have a nested contracts type for a non-generic interface:
[ContractClass(typeof(Foo.FooContracts))]
public interface IFoo
{
string Bar(object obj);
}
But it complains when I try to do the same thing with a generic interface:
[ContractClass(typeof(Foo.FooContracts<>))]
public interface IFoo<T>
{
string Bar(T obj);
}
The warning is:
The contract class Foo+FooContracts`1 and the type IFoo`1 must have the same declaring type if any.
It compiles without a warning if I get FooContracts out of the Foo class.
Why does that limitation exist for generic interfaces?
Why doesn't that limitation exist for non-generic ones?

The reason the limitation exists is that we need to copy contracts from the declaration point to the insertion points and that gets much more complicated if there are generic surrounding classes. There really is no need to have contract classes nested inside other types that I see.

This code compiles on my machine (VS2012, .NET 4.5)
[ContractClass(typeof(Foo.FooContracts<>))]
public interface IFoo<T> {
string Bar(T obj);
}
[ContractClassFor(typeof(IFoo<>))]
public class Foo {
public class FooContracts<T> : IFoo<T> {
public string Bar(T obj) {
throw new NotImplementedException();
}
}
}
I added the ContractClassForAttribute, but I can take it out.
edit: also the ContractClassForAttribute can be applied to the outer or inner class. I don't know which is correct, but neither location affects compilation

Related

Generic Implementation of interface with specified type

I have an interesting situation where I'd like to use a base class utilising a type parameter to implement an interface and also keep things DRY with inheriting classes.
public interface ICalculator
{
void Process(ICalculationModel calculationModel);
}
public abstract class CalculatorBase<T> :ICalculator where T : ICalculationModel
{
// Compiler moans that Process(ICalculationModel calculationModel) isn't implemented
public abstract void Process(T calculationModel);
}
public class PipeworkInspections : CalculatorBase<GasSafetyModel>
{
public override void Process(GasSafetyModel documentModel){
//snip
}
}
Is there something i'm missing with the generic 'where' clause or something? In my head this should work. Or does the compiler need EXACTLY the same implementation as the interface definition?
I can't easily move the type parameter into the ICalculator as there are a lot of places that it is used without any requirement for the generic.
That's cleared things up. Thanks for the info. Now obviously a solution is to make the interface take the type parameter. However ICalculator's are used in a number of places and are referenced just as ICalculator I now get compiler errors if I omit the type parameter in Interfaces that refer to ICalculator... Is there a way to architect this that should work!?
In my head this should work.
The problem then is in your head! :-) This should not work. Let's see why.
interface ICage
{
void Enclose(Animal animal);
}
class ZooCage<T> : ICage where T : Animal
{
public void Enclose(T t) { ... }
}
...
var giraffePaddock = new ZooCage<Giraffe>();
var cage = (ICage)giraffePaddock;
var tiger = new Tiger();
icage.Enclose(tiger);
And now there is a tiger in the giraffe paddock, and life is good for the tiger but bad for the giraffes. That's why this is illegal.
Or does the compiler need EXACTLY the same implementation as the interface definition?
The member which implements an interface member must exactly match the signature of the implemented method. For example, you cannot use return type covariance:
interface I
{
Animal GetAnimal();
}
class C : I
{
public Giraffe GetAnimal() { ... } // not legal.
}
The contract requires an animal; you provide a giraffe. That should work, logically, but this is not legal in C#. (It is in C++.)
See any of the many questions on this site about return type covariance for the reasons why.
Similarly for parameter type contravariance:
interface I
{
void PutMammal (Mammal mammal);
}
class C : I
{
public PutMammal(Animal animal) { ... } // not legal.
}
Again, this is logically sensible; the contract requires that you take a mammal, and this takes any animal. But again, this is not legal.
There are some covariant and contravariant operations in C#; see any of numerous questions on those topics on this site, or browse the covariance and contravariance articles on ericlippert.com or my previous msdn blog.
If this worked then you'd be able to say something like this:
PipeworkInspections pipeworks = new PipeworkInspections();
ICalculator calculator = pipeworks;
NuclearPowerSafetyModel nuclearModel = new NuclearPowerSafetyModel();
calculator.Process(nuclearModel); // <-- Oops!
That's probably not what you wanted...
Your interface says any class implementing it will provide this method:
void Process(ICalculationModel calculationModel);
Now obviously PipeworkInspections does not. It does not have a method Process that accepts any ICalculationModel. IT only has a method accepting specific implementations of ICalculationModel. So your compilation fails.
Yes, you need the exact implementation.
As an alternative you can make interface and Process method generic if it works for you:
public interface ICalculator<T> where T : ICalculationModel
{
void Process(T calculationModel);
}
public abstract class CalculatorBase<T> : ICalculator where T : ICalculationModel
{
public abstract void Process(T calculationModel);
}
I agree with Eric Lippert's response: you can't. And he explained in a very good way why this happens.
If you really want to do this, you can add the following to your abstract class, and it will compile:
void ICalculator.Process(ICalculationModel calcMod)
{
Process((T)calcMod);
}
But you need to know what you are doing, otherwise you might have some InvalidCastException at runtime.

Overriding (shadowing, overloading?) methods with different return types in a C# hierarchy

I'm writing an SDK which has an OOP structure for implementing data types;
first an interface
then an abstract implementation
finally an abstract generic implementation
People can choose to implement either the interface, or derive from either of the classes.
public interface IGoo
{
IGoo Duplicate();
...
}
public abstract class Goo : IGoo
{
IGoo IGoo.Duplicate() {
return Duplicate();
}
abstract public Goo Duplicate();
...
}
public abstract class Goo<T> : Goo
{
abstract public Goo<T> Duplicate(); ??????
...
}
I'd like to re-implement the Duplicate method so that it always returns the most specific type possible. I.e. when you call Duplicate on an IGoo instance, you get another IGoo. If you call it on Goo, you get Goo, if you call it on -say- Goo<int>, you get Goo<int>. And all Duplicate() methods always call the most specific implementation.
Is this possible? Is it only possible when you can implement an interface explicitly? In which case, should I not make Goo<int> derive from Goo, but have it implement IGoo instead and type all the low-level functionality twice?
What about the following?
public interface IObj
{
IObj Duplicate();
}
public abstract class Obj : IObj
{
public Obj()
{
}
public virtual IObj Duplicate()
{
return this;
}
}
public abstract class ObjT<T> : Obj
{
public ObjT()
{
}
public override IObj Duplicate()
{
return this;
}
}
public class ObjImpl : Obj
{
}
public class ObjTImpl : ObjT<int>
{
}
I understand that you want it to return the most specific type possible in any inheriting class but it actually is. It's boxing the inheriting type into the interface (or a raw object if you where to return objects instead of interface types. If you run the following test in a console app you will see the proper type is represented:
namespace TestConsole
{
class Program
{
static void Main(string[] args)
{
ObjImpl a = new ObjImpl();
ObjTImpl b = new ObjTImpl();
Console.WriteLine(a.Duplicate().GetType());
Console.WriteLine(b.Duplicate().GetType());
Console.ReadLine();
}
}
}
// outputs:
// ObjImpl
// ObjTImpl
The idea of redefining abstracts of abstracts goes against the purpose of abstract polymorphism. If the derived types do not intend to implement the inherited abstract member, they should not be inheriting it.
Although the example I gave above would require casting to access any child class-specific members, it would be the proper way to do it in this approach. The runtime needs to know what types it should expect to deal with.
There is always dynamics you could play around with but to be honest I haven't played around with dynamics with generics and inheritance as I suspect I would make my compiler cry, and when it cries, I cry, a little bit deep down inside... lol
It is only possible when you implement the interface explicitly. That's because the return type of a method is not part of its signature - which the compiler checks when overloading. Therefore, otherwise identical methods which only differ in their return type are syntactically not possible.

C# covariance and inheritance

I'm curious to know why the implementation of my interface in the abstract base class does not satisfy the the requirements in sub-classes. Here's an example:
public interface IBase { }
public interface IConcrete : IBase { }
public interface IBaseManager<out T>
where T : IBase
{
T Create();
IEnumerable<T> SelectAll();
}
public interface IConcreteManager : IBaseManager<IConcrete> { }
public abstract class Base : IBase { }
public class Concrete1 : Base, IConcrete { }
public abstract class BaseManager<T> : IBaseManager<T> where T : class, IBase
{
#region IBaseManager<T> Members
public T Create()
{
throw new NotImplementedException();
}
public IEnumerable<T> SelectAll()
{
throw new NotImplementedException();
}
#endregion
}
public class ConcreteManager : BaseManager<Concrete>, IConcereteManager
{
//error occurs here
}
This is the error that is being generated:
'ConsoleApplication4.ConcreteManager' does not implement interface member 'ConsoleApplication4.IBaseManager<ConsoleApplication4.IConcrete>.Create()'.
'ConsoleApplication4.BaseManager<ConsoleApplication4.Concrete>.Create()' cannot implement 'ConsoleApplication4.IBaseManager<ConsoleApplication4.IConcrete>.Create()' because it does not have the matching return type of 'ConsoleApplication4.IConcrete'.
If I add these methods to the ConcreteManager class, everything is fine and the compiler is happy.
public new IConcrete Create()
{
return base.Create();
}
public new IEnumerable<IConcrete> SelectAll()
{
return base.SelectAll();
}
If simply returning what the methods from the base class return is sufficient, why do the methods have to be added? Why can't the compiler call the methods in the base class?
As John points out correctly, the C# language does not support return type covariance. Neither does the CLR, so even if the language supported it, the only way we could actually implement the feature would be to silently generate exactly the code you've had to add yourself.
The small benefit afforded to developers of avoiding having to write those stub methods really does not justify the considerable cost of doing the more general covariance feature, so we've never done it.
It looks like you're assuming return type covariance, since ConcreteManager (as an IConcreteManager) expects both Create() and SelectAll() methods with a return type of IConcrete and IEnumerable<IConcrete> respectively, which the base class does not provide.
You are getting those errors because C# does not support return type covariance.
When you implement an interface/abstract class, you must use the same signature. See here
Don't let the generics throw you off, this is no different than if there were no generics.

What purpose do publicly exposed explicit interfaces serve?

What's the point of a public explicit interface and how does this differ from private?
interface IYer
{
void Hello();
}
interface INer
{
void Hello();
}
class MyClass : IYer, INer
{
public void IYer.Hello()
{
throw new NotImplementedException();
}
public void INer.Hello()
{
throw new NotImplementedException();
}
}
I'm not going to address the code above, which I believe has errors pointed out by others, but I'll answer the question itself.
With explicit interface implementation, you can support multiple interfaces that have conflicting names.
You avoid emphasizing the availability of an interface to clients, when the interface isn't important to most consumers of that class. This is because most languages in the Dotnet framework will require an explicit cast to the interface before you can use methods from explicitly implemented interfaces.
Less important, but I've used them to prevent accidental use of a method or property accessor: Using Explicit Interfaces to prevent accidental modification of properties in C#
There is no public explicit interface implementation. The only way to implement an interface explicitly is to have the method have default accessibility with the interface name prepended to the method name:
class MyClass : IYer, INer
{
//compiles OK
void IYer.Hello()
{
throw new NotImplementedException();
}
//error CS0106: The modifier 'public' is not valid for this item
public void INer.Hello()
{
throw new NotImplementedException();
}
}
This is what MSDN has to say about this:
The public keyword is not allowed on an explicit interface declaration. In this case, remove the public keyword from the explicit interface declaration.
The biggest difference is that your public explicit interfaces are not legal and will not compile. In fact, you should be getting the error, "The modifier 'public' is not valid for explicit interface implementations."

Why collections classes in C# (like ArrayList) inherit from multiple interfaces if one of these interfaces inherits from the remaining?

When I press f12 on the ArrayList keyword to go to metadata generated from vs2008, I found that the generated class declaration as follows
public class ArrayList : IList, ICollection, IEnumerable, ICloneable
I know that the IList already inherits from ICollection and IEnumerable, so why does ArrayList redundantly inherit from these interfaces?
OK, I've done some research. If you create the following hierarchy:
public interface One
{
void DoIt();
}
public interface Two : One
{
void DoItMore();
}
public class Magic : Two
{
public void DoItMore()
{
throw new NotImplementedException();
}
public void DoIt()
{
throw new NotImplementedException();
}
}
And compile it, then reference the DLL in a different solution, type Magic and Press F12, you will get the following:
public class Magic : Two, One
{
public Magic();
public void DoIt();
public void DoItMore();
}
You will see that the interface hierarchy is flattened, or the compiler is adding the interfaces in? If you use reflector you get the same results too.
Update: If you open the DLL in ILDASM, you will see it saying:
implements ...Two
implements ...One.
The extra interfaces are shown because they are implied by IList. If you implement IList, you must also implement ICollection and IEnumerable.
I am just guessing, but I think in reality it only implements IList in code, but the documentation shows the rest of the interfaces as well to make it explicit to the programmer using the class.
From MSDN....
If a class implements two interfaces
that contain a member with the same
signature, then implementing that
member on the class will cause both
interfaces to use that member as their
implementation.
Explicit implementation is also used
to resolve cases where two interfaces
each declare different members of the
same name such as a property and a
method:
Don't accept this as answer.
I am repeating what workmad3 said above.
By implementing it in ArrayList, it becomes easy for one to know - which interfaces ArrayList implements rather that going up to IList to find that it implements ICollection & IEnumerable.
That avoids the need for going back & forth the inheritance chain.
EDIT: At the basic level, an interface implementing another interface cannot provide the implementation. The class derived (from IList) hence indirectly implements ICollection & IEnumerable as well. So, even if you write your own class implementing IList (and not add ICollection, IEnumerable in the declaration) - you will see that it will have to provide the implementation for ICollection & IEnumerable.
And workmad3's reasoning makes sense.
My guess would be that the CLR does not support an interface that inherits from another interface.
C# however does support this construct but has to 'flatten' the inheritance tree to be CLR compliant.
[Edit]
After taking advise from below quickly setup a VB.Net project:
Public Interface IOne
Sub DoIt()
End Interface
Public Interface ITwo
Inherits IOne
Sub DoIt2()
End Interface
Public Class Class1
Implements ITwo
Public Sub DoIt() Implements IOne.DoIt
Throw New NotImplementedException()
End Sub
Public Sub DoIt2() Implements ITwo.DoIt2
Throw New NotImplementedException()
End Sub
End Class
Compiling results in the following (C#):
public class Class1 : ITwo
{
public Class1();
public void DoIt();
public void DoIt2();
}
This show that VB.Net does NOT flatten the interface hierarchy as opposed to C#. I have no clue as to why this would be.
ArrayList is supposed to explicitly contain ICollection and IEnumerable implementations, just like the IList interface, which contains ICollection and IEnumerable implementations. But the ArrayList implementation should not be dependent on IList. In such a way that if the list structure changes, no effect will be felt on the ArrayList behavior. So they must be considered completely independent.
Inheriting ICollection and IEnumerable is important to ensure ArrayList independence. So if the IList structure changes and does not run ICollection or IEnumerable, the ArrayList structure will not change.
For example:
If you create the following hierarchy:
public interface IOne
{
void DoIt();
}
public interface ITwo : IOne
{
void DoItMore();
}
public class Magic : ITwo
{
public void DoItMore()
{
throw new NotImplementedException();
}
public void DoIt()
{
throw new NotImplementedException();
}
}
Now interface ITwo decides not to use IOne implementation in its implementation. Since we explicitly inherited from IOne in the implementation of Magic, the program runs independently and does not depend on changes to the ITwo interface.
public interface IOne
{
void DoIt();
}
public interface ITwo
{
void DoItMore();
}
public class Magic : ITwo,IOne
{
public void DoItMore()
{
throw new NotImplementedException();
}
public void DoIt()
{
throw new NotImplementedException();
}
}
Update: If you look at the .NET source code and Microsoft documentation, you will see that the generated metadata is different from what you mentioned in the question.
This probably goes back to how IL emitted

Categories

Resources