Generic collection collision - c#

Here's my best attempt to recreate the situation.
public interface IFoo
{
}
public class Foo : IFoo { }
public class Bar : IFoo { }
public class CollectionOf<T> : List<IFoo>
{
}
public class Bars : CollectionOf<Bar>
{
}
public class Test
{
public void Test()
{
CollectionOf<IFoo> bars = new Bars();
}
}
Compiler complains on the instantiation. Bars is a collection of IFoos. Is this one of those covariance/contravariance issues?

Yes.
Think about it for a second; bars should legally be able to hold objects of any type that implement IFoo. However, an object of type Bars can only hold objects of type Bar.
Using your code this would be allowed, which is obviously wrong.
CollectionOf<IFoo> bars = new Bars();
bars.Add( new Foo() ); // Uh oh!
That would effectively break the type safety afforded to you via generics.

Yes it is.
If this was allowed, you would be able to place any object into that collection, as long as it implemented the IFoo interface, but that wouldn't be safe for the collection.
Let me illustrate:
var b = new Bars();
CollectionOf<IFoo> bars = b;
bars.Add(Dummy); // implements IFoo, but does not descend from Bar
At this point, what does b contain? An object of type Dummy? That would be bad, and thus this is not allowed in the first place.

The fix, if there is one would depend on what it is that's not working for you. I can get your example to compile in two ways, either use IEnumerable or define your CollectionOf as an interface with the out generic modifier. Whether either is a fix for you I don't know:
public interface IFoo { }
public class Foo : IFoo { }
public class Bar : IFoo { }
public interface CollectionOf<out T> : IEnumerable<IFoo> { }
public class Bars : CollectionOf<Bar> { }
public class Test
{
public void Test()
{
IEnumerable<IFoo> bars1 = new Bars();
CollectionOf<IFoo> bars2 = new Bars();
}
}

Related

instantiate abstract class on the spot

In Java I can instantiate an on-the-spot implementation of an interface:
interface Rubbable {
public void rub();
}
...
Rubbable r = new Rubbable() {
#Override
public void rub() {
// implementation
}
};
Like, a one-time implementation kind of thing.
I've tried to do the same thing with an abstract class in C#
public abstract class Foo
{
public abstract Bar Method();
}
Foo f = new Foo
{
public override Bar Method()
{
return new Bar();
}
}
But I'm getting the error
Cannot create an instance of the abstract type or interface 'Foo'
Can I instantiate an abstract class on-the-spot as I would like to? Some kind of, one-time-implementation without having to dedicate a whole class declaration in another part of the codebase to it.
Such a feature is not available in c#. A workaround could be to use delegates:
public class DelegateFoo : Foo {
private Func<Bar> barMethod();
public DelegateFoo(Func<Bar> tmp) => barMethod = tmp;
public override Bar Method() => barMethod();
}
var f = new DelegateFoo(() => new Bar());
But in such a simple case I the class does not add anything, so you might as well use a delegate directly.

How to specify children classes to use their type?

Lets say I have a class such as this:
public abstract class Foo
{
public void Access(Foo foo)
{
/*
if (foo is same type as implemented)
AccessIfSameImplementation(foo);
else
AccessIfDifferentImplementation(foo);
*/
}
protected abstract void AccessIfSameImplementation(Foo foo);
private void AccessIfDifferentImplementation(Foo foo)
{
//do stuff with the different implementations
}
}
So the method Access takes a type of itself, by definition it will be an implementation in which we don't really care what it is as long as it inherits from Foo... But I want this method to check if the object passed in is the same type as its implementation.
Like so:
public class Bar : Foo
{
protected override void AccessIfSameImplementation(Foo foo)
{
// TODO: How do I force foo to always be a Bar
// do specific Bar stuff
}
}
Currently I have a Name field that indicates if the passed in foo.Name is the same as the current Name Besides that I thought about using generics but again don't think that's the right approach to this problem.
EDIT:
A little background on the actual structures I'm using.
The Foo class defined above is representative of a factory that creates a set of objects List<X> objs these objects are generated by the properties of the implemented Foo object. Now I have some other class comparing these factories but I don't wish for the factories to be, *bloated out by generating them all. So instead of *bloating the factories out I simply check if they have the same implementation, if so compare properties defined by the abstract comparer otherwise *blowout. I will add more later when I have some time.
If anyone has a better title please recommend one.
Aright so I guess I just can't think things entirely through. All that needs to be done is a type comparison directly in the public method Access
public void Access(Foo foo)
{
if (GetType() == foo.GetType) //Duh...
{
AccessIfSameImplementation(foo);
}
else
{
AccessIfDifferentImplementation(foo);
}
}
I'm not totally sure what your intention is, but you can't change the signature of an abstract method in the child class. One thought would be to do an argument check and throw an exception if you ever got an inappropriate foo:
public abstract class Foo
{
public void Access(Foo foo)
{
if (foo.GetType() == GetType())
{
AccessIfSameImplementation(foo);
}
else
{
AccessIfDifferentImplementation(foo);
}
}
protected abstract void AccessIfSameImplementation(Foo foo);
private void AccessIfDifferentImplementation(Foo foo)
{
//do stuff with the different implementations
}
}
public class Bar : Foo
{
public string Baz { get; set; }
protected override void AccessIfSameImplementation(Foo foo)
{
var bar = foo as Bar;
if (bar == null)
{
throw new ArgumentException("Argument foo is not of type Bar");
}
//Do Bar stuff below
bar.Baz = "Yay!";
}
}
Keep it simple. Keep your abstract class abstract, but give the Access method a default implementation that is Foo agnostic. Leave it up the a child class to provide custom implementation that uses members of that child class. You could also make it optional for the child class to fall back on the default logic implemented in the base class:
public abstract class Foo
{
public virtual void Access(Foo foo)
{
// perform the default implementation here, but mark as virtual to enable a child class to override it.
}
}
public class Bar : Foo
{
public override void Access(Foo foo)
{
var bar = foo as Bar;
if (bar != null)
{
// If you get here, that means foo is a Bar.
// Just use bar now and ignore foo.
}
else
{
// Fall back on the base classes implementation
base.Access(foo);
}
}
}

Is there any way an interface can cause different behavior?

Say I have the following code:
class Foo: IFoo {
public string fooProp { get; set; }
}
interface IFoo {
string fooProp {get; set; }
}
Is it at all possible for there to be different behavior between:
Foo x = new Foo();
someMethod(x);
and:
IFoo x = new Foo();
someMethod(x);
?
I think it may differ. If somebody's used bad style of programming, i.e.:
public void someMethod(IFoo f)
{
if (f is Foo)
{
Foo f1 = (Foo)f;
//Do smth with unique Foo members
}
//Do anything with IFoo members
}
Yes, there is a difference if someMethod has different overloads for IFoo and Foo.
public void someMethod(Foo f)
{
// Overload 1
}
public void someMethod(IFoo f)
{
// Overload 2
}
Foo x = new Foo();
someMethod(x); // Matches overload 1
IFoo x = new Foo();
someMethod(x); // Matches overload 2
(I'm no expert) but in your first scenario, you would get access to everything in Class Foo. In the second scenario, you would only be able to access the IFoo members. So if Foo has additional methods (that aren't part of the interface), you will be able to access them in your first scenario but not the second.
I believe using the interface name instead of the class name is just another way to encapsulate data and only provide access to the interface members. For instance you could have Foo and Bar which both implements IFoo. You could add both of them to, say, a List.
There would never be any difference.
Remember, an interface is a contract. By deriving Foo from IFoo, you are implementing that contract.
In both cases, because Foo is an IFoo and adheres to the contract, the behaviour will always be the same.
Of course, how Foo implements that contract is anybodies guess. But the contract is adhered too by the signature of the interface.
If you have two interfaces and there is a common method name in each of them then the implementing class can implement the same method differently. The it depends how the method is called - via interface or not and via which interface.
See here for a similar question:
Inheritance from multiple interfaces with the same method name
Different bahavior can be, but inside someMethod.
Say you have
class Foo: IFoo {
public fooProp { get; set; }
}
interface IFoo {
fooProp {get; set; }
myCustomProp {get;set}
}
if you have
public void someMethod(Foo _foo){
_foo.myCustomProp; //CAN DO THIS, AS YOUR TYPE IS _FOO_
}
Which will not be possible to do in case when the parameter of the method is defined like.
public void someMethod(IFoo _foo){
_foo.myCustomProp; //NO SUCH METHOD INFO
}
unless you don't cast. So the difference is that decaring IFoo, to decalre generic access parameter, but get less "potential" in terms of data access, but get a huge potential in abstraction over types in your architecture.
So the difference will be only in regard of architecture and program workflow.
You could have an explicitly implemented interface in Foo.
class Foo: IFoo {
private string _fooprop;
private string _ifooprop;
public string fooProp
{
get {return "IFoo";}
set {_fooprop=value;}
}
string IFoo.fooProp
{
get {return "Foo";}
set {_ifooprop=value;}
}
}
interface IFoo {
string fooProp {get; set; }
}
with this, you will have:
IFoo foo1=new Foo();
Foo foo2=new Foo();
Console.WriteLine(foo1.fooProp); // Foo
Console.WriteLine(foo2.fooProp); // iFoo
It's possible if you explicitly implement IFoo:
public class Foo : IFoo
{
public string Prop
{
get { return "Hello Foo"; }
}
string IFoo.Prop
{
get { return "Hello IFoo"; }
}
}
public static void SomeMethod<T>(T foo) where T : IFoo
{
var prop = typeof(T).GetProperty("Prop");
Console.WriteLine(prop.GetValue(foo));
}

Two way reference with interfaces and generics

I've got a class with generics which uses another class, which in return needs to know what instance of the initial class "owns" it - which causes problems ;) Let me give an example:
public interface IFoo<T>
{
}
public interface IBar
{
IFoo<IBar> Foo { get; set; }
}
public class Foo<T> : IFoo<T> where T : IBar, new()
{
private readonly T _bar;
public Foo()
{
_bar = new T {Foo = this};
}
}
class Bar : IBar
{
public IFoo<IBar> Foo { get; set; }
}
This doesn't work as Foo = this doesn't work - even if I try to cast this to IFoo (compiles but fails at run time). I've tried to tweak the code various ways, but I've not found an implementation that works...
Hopefully you see what I'm trying to do, and perhaps you even see how I can achieve this ;-)
You can solve this with a combination of an explicit cast in the constructor, along with c#4.0 support for covariance on generic parameters.
First, you need to insert a cast in the Foo<T> constructor:
_bar = new T {Foo = (IFoo<IBar>)this};
Just doing that isn't sufficient, though. Your constraint that T : new() means that T needs to be a concrete class. As such, IFoo<T> will never be exactly IFoo<IBar>. However, if you specify that the generic parameter T for IBar<T> is covariant, then the cast from IFoo<Bar> to IFoo<IBar> will become legal:
public interface IFoo<out T>
The out keyword specifies that the parameter is covariant (which essentially means "this parameter will only be output by methods, never input.")
This MSDN article offers more details on covariance and contravariance.
Would declaring the T type parameter of IFoo as covariant solve your problem?
This code should allow you to do what you are trying:
public interface IFoo<out T> {
}
public interface IBar {
IFoo<IBar> Foo { get; set; }
}
public class Foo<T> : IFoo<T> where T : IBar, new() {
private readonly T _bar;
public Foo() {
_bar = new T { Foo = (IFoo<IBar>)this };
}
}
class Bar : IBar {
public IFoo<IBar> Foo { get; set; }
}
public static class Program {
public static void Main(params string[] args) {
Bar b = new Bar();
Foo<Bar> f = new Foo<Bar>();
}
}

Is it possible to specify a generic constraint for a type parameter to be convertible FROM another type?

Suppose I write a library with the following:
public class Bar { /* ... */ }
public class SomeWeirdClass<T>
where T : ???
{
public T BarMaker(Bar b)
{
// ... play with b
T t = (T)b
return (T) b;
}
}
Later, I expect users to use my library by defining their own types which are convertible to Bar and using the SomeWeirdClass 'factory'.
public class Foo
{
public static explicit operator Foo(Bar f)
{
return new Bar();
}
}
public class Demo
{
public static void demo()
{
Bar b = new Bar();
SomeWeirdClass<Foo> weird = new SomeWeirdClass<Foo>();
Foo f = weird.BarMaker(b);
}
}
this will compile if i set where T : Foo but the problem is that I don't know about Foo at the library's compile time, and I actually want something more like where T : some class that can be instantiated, given a Bar
Is this possible? From my limited knowledge it does not seem to be, but the ingenuity of the .NET framework and its users always surprises me...
This may or not be related to the idea of static interface methods - at least, I can see the value in being able to specify the presence of factory methods to create objects (similar to the same way that you can already perform where T : new())
edit: Solution - thanks to Nick and bzIm - For other readers I'll provide a completed solution as I understand it:
edit2: This solution requires Foo to expose a public default constructor. For an even stupider better solution that does not require this see the very bottom of this post.
public class Bar {}
public class SomeWeirdClass<T>
where T : IConvertibleFromBar<T>, new()
{
public T BarMaker(Bar b)
{
T t = new T();
t.Convert(b);
return t;
}
}
public interface IConvertibleFromBar<T>
{
T Convert(Bar b);
}
public class Foo : IConvertibleFromBar<Foo>
{
public static explicit operator Foo(Bar f)
{
return null;
}
public Foo Convert(Bar b)
{
return (Foo) b;
}
}
public class Demo
{
public static void demo()
{
Bar b = new Bar();
SomeWeirdClass<Foo> weird = new SomeWeirdClass<Foo>();
Foo f = weird.BarMaker(b);
}
}
edit2: Solution 2: Create a type convertor factory to use:
#region library defined code
public class Bar {}
public class SomeWeirdClass<T, TFactory>
where TFactory : IConvertorFactory<Bar, T>, new()
{
private static TFactory convertor = new TFactory();
public T BarMaker(Bar b)
{
return convertor.Convert(b);
}
}
public interface IConvertorFactory<TFrom, TTo>
{
TTo Convert(TFrom from);
}
#endregion
#region user defined code
public class BarToFooConvertor : IConvertorFactory<Bar, Foo>
{
public Foo Convert(Bar from)
{
return (Foo) from;
}
}
public class Foo
{
public Foo(int a) {}
public static explicit operator Foo(Bar f)
{
return null;
}
public Foo Convert(Bar b)
{
return (Foo) b;
}
}
#endregion
public class Demo
{
public static void demo()
{
Bar b = new Bar();
SomeWeirdClass<Foo, BarToFooConvertor> weird = new SomeWeirdClass<Foo, BarToFooConvertor>();
Foo f = weird.BarMaker(b);
}
}
Sounds like you found a solution to the larger problem. To answer your specific question: no, neither C# nor the CLR support the "backwards" generic type parameter constraint. That is,
class C<T> where Foo : T
"T must be Foo or a type which Foo converts to" is not supported.
There are languages that have that sort of constraint; IIRC Scala is such a language. I suspect this feature would be handy for certain uses of contravariant interfaces.
I don't think there is necessarily a syntactically cool way to do this built into the language. One possible solution to your problem could be to define a convertible interface:
public interface IConvertible<T>
where T : new() // Probably will need this
{
T Convert();
}
Then your class could be:
public class Foo : IConvertible<Bar>
{
}
I think this gets you close to where you want to be... All the Foo's and Bar's in your question sometimes make it hard to determine exactly what your intent is. Hope this helps.
Edit: Added where constraint... you will probably have to be able to create a new instance in your convertible class.
Edit 2: Made Foo inherit from ICovertible<Bar>
You could make a detour via an interface which is used as a type constraint.
For example, where T : IComparable<U> is used to constrain the type to something that can be compared to another thing, which must express this ability by implementing IComparable<another>. If you had an interface ICastableFrom<T>, you could achieve what you want by forcing them to implement ICastableFrom<Bar>.
Rather than go through the trouble of defining an interface and modifying your class to implement that interface, why not just do this?
public class SomeWeirdClass<T>
{
// aside: why is this method called 'BarMaker' if it returns a T?
public T BarMaker(Bar b, Func<Bar, T> converter)
{
// ... play with b
return converter(b);
}
}
Then in the event that you are dealing with an object of a type T to which Bar can be directly cast, this method could be called simply as follows:
var someWeirdObject = new SomeWeirdClass<Foo>();
var someBar = new Bar();
var someFoo = someWeirdObjcet.BarMaker(someBar, bar => bar as Foo);
By the way (since the Func<T, TResult> delegate emerged in .NET 3.5), you could also use Converter<TInput, TOutput> (which is exactly the same) for the converter parameter.

Categories

Resources