Can you attach an interface to a defined class - c#

Here is the situation. In some cases I find myself wanting a class, let's call it class C that has the same functionalities as class A, but with the addition that it has interface B implemented. For now I do it like this:
class C : A,B
{
//code that implements interface B, and nothing else
}
The problem will come if class A happens to be sealed. Is there a way I can make class A implement interface B without having to define class C (with extension methods or something)

Basically: no. That is part of what "mixins" could bring to the table, but the C# languauge doesn't currently support that (it has been discussed a few times, IIRC).
You will have to use your current approach, or (more commonly) just a pass-through decorator that encapsulates A rather than inheriting A.
class C : IB
{
private readonly A a;
public C(A a) {
if(a == null) throw new ArgumentNullException("a");
this.a = a;
}
// methods of IB:
public int Foo() { return a.SomeMethod(); }
void IB.Bar() { a.SomeOtherMethod(); }
}

The only way I see, is to change inheritance to aggregation, like this:
class C : B
{
public C(A instanceToWrap)
{
this.innerA = instanceToWrap;
}
//coda that implements B
private A innerA;
}
There seems to be a possibility to inject interface in run-time, as it is done with Array class and IEnumerable<T> interface, but it seems a bit of an overkill.

Is there a way I can make class A implement interface B without having to define class C (with extension methods or something)
The short answer is no. You can't make A implement B because you don't have control of A. However, I think you're headed down the right road with extension methods. Consider this:
public static class AImplementsBExtensions
{
public static void Func1(this A o) { }
public static void Func2(this A o) { }
}
Now clearly I have no idea what methods exist on B, but this is how you can implement B on A when you can't inherit from it.
Bear in mind, this is not an implementation. If you add or remove methods from the interface you'll have to do that by hand here. But now you can do this:
var a = new A();
a.Func1();

You could try creating your class without the inheritance: class C : B and as a wrapper around A.
Additionally you can provide implicit conversion operators so that code like A obj = new C(new A()) would work similar to how a derived class would work.
class C : B
{
private A _inner;
public C(A inner)
{
this._inner = inner;
}
public A Inner { get { return this._inner; } }
public static implicit operator A(C obj)
{
return obj == null ? (A)null : obj._inner;
}
public static implicit operator C(A obj)
{
return new C(obj);
}
}

Related

Method return type polymorphism

I have 4 C# classes; Job, BuildJob, JobFactory and BuildJobfactory. Below are the MVPs of each class.
public class Job {
}
public abstract class JobFactory {
public abstract List<Job> GetJobs(List<B> bs);
}
public class BuildJob : Job {
A a;
B b;
public BuildJob(A a, B b) {
this.a = a;
this.b = b;
}
}
public class BuildJobFactory : JobFactory {
A a;
public override List<Job> GetJobs(List<B> bs) {
return bs.ConvertAll(b => new BuildJob(a, b));
}
}
JobFactory is used to create a load of jobs from a list of B instances, and the way that those jobs are constructed will depend on their types (BuildJob, DestroyJob et.c) so this has to be left to a factory class. As I come from a Java background, I assumed that returning a List<BuildJob> from a method whose return type is declared as List<Job> would be fine, as BuildJob extends Job, but this does not work in C#.
To alleviate this, I then tried generics so the modified classes looked like so.
public abstract class JobFactory<T> where T : Job, new() {
public abstract List<T> GetJobs(List<B> bs);
}
public class BuildJobFactory : JobFactory<BuildJob> {
A a;
public override List<BuildJob> GetJobs(List<B> bs) {
return bs.ConvertAll(b => new BuildJob(a, b));
}
}
I tried to make a variable of type JobFactory without a generic declaration (Jobfactory currentJobFactory;) as it will be unknown at compile time, since at runtime the variable will be assigned to some instance of some class that extends JobFactory with some unknown generic, but this does not work as it does in Java.
How could I solve one of these problems?
Try:
public override List<Job> GetJobs(List<B> bs) {
return bs.Select(b => new BuildJob(a, b)).Cast<Job>().ToList();
}
Edit: If Select() is unavailable, you probably need to add the following to the beginning of your file:
using System.Linq;
This will instruct the compiler to search for extension methods (which Select() is one of) in the System.Linq namespace.
What this is doing:
bs.Select() iterates over the bs list, executing the lambda on each one, resulting in an IEnumerable<BuildJob>. .Cast<Job>() converts that to an IEnumerable<Job>, and finally, .ToList() converts the IEnumerable<Job> to a List<Job>.
All that said, I would consider changing the signatures of your methods to return IEnumerable<Job>, which would remove the need for the .Cast<Job>().ToList().
You cannot return a List of BuildJobs as a List of Jobs, but you can add a BuildJob to a List of Jobs.
For Example:
public override List<Job> GetJobs(List<B> bs) {
List<Job> temp = new List<Job>();
foreach (var b in bs) {
temp.Add(new BuildJob(new A(), b));
}
return temp;
}
Not as slick and inline as a LINQ statement, but functional.
I agree with the rest that IEnumerable is a better return type, as well.
Use IEnumerable<T> or IReadOnlyCollection<T> instead of List<T> as both of these interfaces support covariance. It's considered bad practise to return concrete collection types anyway because it exposes lots of implementation details.
Choose IEnumerable<T> if you want deferred exceution and IReadOnlyCollection<T> if you don't.
public class Job
{ }
public abstract class JobFactory
{
public abstract IEnumerable<Job> GetJobs(IEnumerable<B> bs);
}
public class BuildJob : Job
{
A a;
B b;
public BuildJob(A a, B b)
{
this.a = a;
this.b = b;
}
}
public class BuildJobFactory : JobFactory
{
A a;
public override IEnumerable<Job> GetJobs(IEnumerable<B> bs)
{
return bs.Select(b => new BuildJob(a, b));
}
}
See: https://msdn.microsoft.com/en-gb/library/mt654055.aspx for more info on covariance and contravariance.
Generics in C# are much more strict than they are in Java. You can't leave out the generic and default to the interpretation that everything is an Object. However, you can use Covariance to work around the situation.
If you change the generic so that it looks like this:
public abstract class JobFactory<out T>
where T : Job, new()
{
public abstract List<T> GetJobs(List<B> bs);
}
Then you have the ability to freely cast the JobFactory<BuildJob> to JobFactory<Job> without issue. This is the way IEnumerable<out T> is defined. You can build the logic for your core code around the base assumption, but specialize things further down the line.
Basically it means you can do this:
JobFactory<BuildJob> derivedFactory = new JobFactory<BuildJob>();
JobFactory<Job> baseFactory = derivedFactory;
Or more directly you can use code that looks like this:
public class Container
{
public JobFactory<Job> Factory { get; set; }
}
and later on assign that property like this:
Container myContainer = new Container {
Factory = new JobFactory<BuildJob>()
};

How to restrict generic function to accept only some type of classes

I'm trying to do the following:
public class A
{
}
public class B
{
}
Somewhere along the project I want to have this:
public class C
{
public T func<T>(T obj) [where T can be either of class A or class B]
{
obj.x = 100;
return obj;
}
}
I've been trying:
public T func<T>(T obj) where T: A, B
but this gives me:
The type class constraint 'B' must come before any other constraint.
Can someone explain me how to make func accept only class A or class B?
Exactly as it's described in the question, this job is better handled by overload resolution:
public class C
{
public A func(A obj)
{
obj.x = 100;
return obj;
}
public B func(B obj)
{
obj.x = 100;
return obj;
}
}
But I understand that A and B may be placeholders for any number of types, and it could get tedious to account for them all. In that case, you'll need a common interface that's supported by each of your classes:
interface IBase
{
int x;
}
public class C
{
public IBase func(IBase obj)
{
obj.x = 100;
return obj;
}
}
Note that at this point we still have no need of generics. Additionally, you may need to support a number of types that won't all fit together under a common interface. In this case, still build the interface and put as many types with that interface as possible. If needed, build another interface for a few more types ... and so on... and then between interfaces and specific types you can handle things with overload resolution.
You need some kind of common base for both the classes, either have them implement the same interface as the below code or have them inherit from same class. You can not have a generic constrained to 2 types.
public interface IFooBar
{
void DoThis();
}
public class Foo : IFooBar
{
public void DoThis()
{
//Do something
}
}
public class Bar : IFooBar
{
public void DoThis()
{
//Do something
}
}
public class C
{
public T func<T>(T obj) where T : IFooBar
{
obj.DoThis();
return obj;
}
}
The generics classes are just like any other class, you can't (and shouldn't) have multiple inheritance of classes, you can inherit one class and multiple interfaces.
in your case you should apply an interface on both classes and restrict the generics on that interface.
you can see some documentation in:
Constraints on Type Parameters (C# Programming Guide)
interface IMarkerInterface{} // there is a such pattern called marker
// interface . No need to have methods if there
// is no need for, A and B can just implement it
public class A: IMarkerInterface
{
}
public class B: IMarkerInterface
{
}
public class C
{
public T func<T>(T obj).Where T:IMarkerInterface
{
obj.x = 100;
return obj;
}
}
public T func<T>(T obj) where T: A, B this means T should extend both A and B , but multiple inheritance is not valid in C# ,so it won't work.
You could do one of the following though :
you could make A and B have a common parent via an interface or an abstract class , but that would be code modification.
since both A and B have a default no-arg constructor you could use where T: new().
Also, you can not do obj.x = 100; as there is no way to guarantee thatT will have a instance variable x.

Using the new-keyword to join a method of two interfaces

I have two Interfaces A,B (residing in different components). Both declare a method with the same signature ( MyMethod ). The two interfaces are inherited by a third Interface (C).
The method which is declared in the first two interfaces (A,B) is intended to return always the same values (for A and B) and thus, I don’t want to implement the interfaces explicitly when deriving from C.
I achieve this with declaring the method also in the third interface, while using the new-keyword.
public interface A {
MyType MyMethod();
}
public interface B {
MyType MyMethod();
}
public interface C : A,B{
new MyType MyMethod();
}
public class ImplementingClass : C{
public MyType MyMethod(){
// do somethin
// return something
}
}
Are there problems to be expected with this, or is this bad style?
Update
Sorry, my initial question has not shown the full story. The Problem arises, when I try to call MyMethod on a interface-reference of C. The Compiler will not compile this.
C aReferenceToC=new CImplementingClass();
aReferenceToC.MyMethod(); // <<< Here the compiler will throw an exception
Full example
C myCImplementationAsAnInterfaceReference = new MyCImplementation();
myCImplementationAsAnInterfaceReference.MyMethod(); // This does not compile without declaring MyMethod in C with the new-Keyword
MyCImplementation myCImplementationReference= new MyCImplementation();
myCImplementationReference.MyMethod(); // This however will always compile and run
public interface A {
int MyMethod();
}
public interface B {
int MyMethod();
}
public interface C : A, B {
}
public class MyCImplementation : C {
public int MyMethod() {
return 1;
}
}
Doing what you do, does not in any way stop people from giving different implementations of A.MyMethod, B.MyMethod, and C.MyMethod.
class TestABC : C
{
MyType C.MyMethod()
{
// 1
return null;
}
MyType A.MyMethod()
{
// 2
return null;
}
MyType B.MyMethod()
{
// 3
return null;
}
}
The new keyword does not in anyway remove the "hidden" method. It just tells the compiler to tolerate the fact that the type has now two identical methods with the same signature, one inherited from a base type, and one declared by the current type.
Edit: OK, given the development of your question, here's what I think your problem really was (this wasn't clear to me initially):
You had this design:
public interface A {
MyType MyMethod();
}
public interface B {
MyType MyMethod();
}
public interface C : A,B{
}
Your problem was that this code didn't compile:
C myInstance = CreateAnInstanceOfSomeClassImplementingC();
myInstance.MyMethod(); // does not compile, ambiguous
Your question is if it's an OK solution to get rid of the compiler error error CS0121: The call is ambiguous between the following methods or properties: [...] by introducing the new member in C.
To me it seems ugly. But i cannot come up with another solution (when you informed me in the comments that C could not be a class). There's no way for an interface to dictate that two methods inherited must unite.
Whether using new keyword or not does not really change anything here. the behavior is just the same.
Testing testing = new Testing();
testing.MyMethod(); // calls Testing.MyMethod
AA testingA = new Testing();
testingA.MyMethod(); // calls AA.MyMethod
public interface A
{
int MyMethod();
}
public class AA : A
{
public int MyMethod()
{
return 11;
}
}
public interface B
{
int MyMethod();
}
public interface C : A, B
{
int MyMethod();
}
public class Testing : AA,C
{
public int MyMethod()
{
return 10;
}
}

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.

Typing polymorphic values with multiple interfaces in C#

Is there any type-safe, compile-time checked possibilty of referring to values that implement multiple interfaces?
Given
interface A {
void DoA();
}
interface B {
void DoB();
}
I'm able to write code for objects implementing A or B, but not both. So I've to come up with ugly wrappers:
class ABCollection {
private class ABWrapper : A, B {
private readonly A a;
private readonly B b;
public static ABWrapper Create<T>(T x) where T : A, B {
return new ABWrapper { a = x, b = x };
}
public void DoA() {
a.DoA();
}
public void DoB() {
b.DoB();
}
}
private List<ABWrapper> data = new List<ABWrapper>();
public void Add<T>(T val) where T : A, B {
data.Add(ABWrapper.Create(val));
}
}
Is there a trick to write this code more intuitively without losing type-safety (runtime-casts etc.)?
E.g.
private List<A and B> ...
Edit: This is not about having a list in particular - I just wanted to give a "complete" example with the issue of storing such values. My problem is just how to type a combination of both interfaces (like A & B or A and B).
Another more useful example: List<IDrawable & IMovable> ...
You can do parametric polymorphism like that in C#, but not subtype polymorphism. That is, you can create a polymorphic method like:
void Foo<T>(T t) where T : IFoo, IBar
{
t.Foo();
t.Bar();
}
and then you must pass an object whose type is known at compile time to implement both IFoo and IBar.
But there is no way to say
void Foo(IFoo-and-IBar t)
{
t.Foo();
t.Bar();
}
and then pass in a value that is both an IFoo and an IBar. Neat feature, but not one we support.
Well, as Eric Lippert said, there's no IFoo-and-IBar type you can use as a method parameter type.
However, I was playing around with some ideas and came up with an alternate way of using your wrapper class that may be better. I'll leave that up to you (or whoever else might search for this question) to decide:
CLASSES
public abstract class ABWrapper : IA, IB
{
private readonly IA a;
private readonly IB b;
protected ABWrapper( IA a, IB b ) { this.a = a; this.b = b; }
// Implement methods on IA and IB
}
public sealed class ABWrapper<T> : ABWrapper
where T : IA, IB
{
private ABWrapper( T a, T b ) : base( a, b ) { }
public static implicit operator ABWrapper<T>( T t )
{
if ( t == null ) return null;
return new ABWrapper<T>( t, t );
}
}
EXAMPLE
public class AB : IA, IB { }
void Method( ABWrapper x )
{
}
void Main()
{
AB x = null;
Method( (ABWrapper<AB>) x );
}
The icky thing about this is that you need to do a cast to ABWrapper<T> at every call site. You could also create an extension method ABWrapper ToABWrapper<T>(this T t) where T : IA, IB to replace the cast if that would be more preferable.
It would be cool if the compiler could reason that an implicit conversion from AB to ABWrapper exists via implicit conversions to and from ABWrapper<T>. There's probably a very good reason it doesn't try to do that, however.
However, what you gain is the ability to put ABWrapper all throughout your method parameters without needing to genercize the methods.
I'm not clear on why you'd want to do this. If you did, you could declare a base interface:
interface AorB {}
interface A : AorB {
void DoA();
}
interface B : AorB {
void DoB();
}
and store those in the collection. Of course you'd have to is- or as-cast when retrieving (standard extension methods could help here).
It seems to me that this is a possible violation of SRP, and the collection is doing too much. Alternately the interfaces are too finely-grained.

Categories

Resources