Constructing two objects that need each other - c#

A puzzling architectural question: You have two symmetrical classes A and B. Each A/B object may privately produce a value of type IA/IB using the A.CreateIA()/B.CreateIB() methods. These values are needed by the opposite classes - A needs IB and B needs IA.
The goal is to write the PairMaker.MakePair() function that constructs an interlinks a pair of A and B objects. You also have to write appropriate constructors for the A and B classes. A and B classes are in different assemblies and don't see each other's internals. The link should be secure - the external code should not be able to access or modify the object fields. You can write additional classes and add any methods to A and B as needed - just don't break the security of the link.
interface IA { }
interface IB { }
class A {
IB ib;
//Some constructor
//Other members
IA CreateIA() { }
}
class B {
IA ia;
//Some constructor
//Other members
IB CreateIB() { }
}
class PairMaker {
public static Tuple<A, B> MakePair() {
//What's here?
}
}
This question is similar to How to construct two objects, with each other as a parameter/member, but that question wasn't answered properly.

Here is a possible solution. I don't like how it looks (I hate those out parameters in the constructors).
class A {
IB _ib;
public A(out Func<IA> getter, out Action<IB> setter) {
getter = CreateIA;
setter = SetIB;
}
void SetIB(IB ib) {
_ib = ib;
}
IA CreateIA() { throw new NotImplementedException(); }
}
class B {
IA _ia;
public B(out Func<IB> getter, out Action<IA> setter) {
getter = CreateIB;
setter = SetIA;
}
void SetIA(IA ia) {
_ia = ia;
}
IB CreateIB() { throw new NotImplementedException(); }
}
.
class PairMaker {
public static Tuple<A, B> MakePair() {
Func<IA> iaGetter;
Func<IB> ibGetter;
Action<IA> iaSetter;
Action<IB> ibSetter;
A a = new A(out iaGetter, out ibSetter);
B b = new B(out ibGetter, out iaSetter);
iaSetter(iaGetter());
ibSetter(ibGetter());
return Tuple.Create(a, b);
}
}

Related

Change return type to derived type during override

I would like to have interace A. Which will allow objects of type A generate other objects of type A.
I need the same behavior for type B. In my application is true that all B are also A. So I would like B to be derived from A.
This is my try:
public interface A {
A method1();
}
public interface B : A {
overrride B method1();
void otherMethod();
}
Note that override keyword dosn't compile here. The only way to make the project compile is make the interface B look as follows:
public interface B : A {
//A method1(); /* commented out because it is inherired */
void otherMethod();
}
However I would like to promise by interface B, that objects of this type have method to produce other objects of type B.
Implementation of interface B could look like:
class Foo : B {
B metod1();
}
Where I want B metod1() to be implemantation of B method1() from interface B and I also want the same method to be implementation of A method1() from interface A. I expect the same behavior in all classes implementing interface B. So I don't want to implement method1 each time twice for both interfaces.
I am doing this in c# with interfaces. But I believe that similar question could be interesting even with classes and possibly also in Java.
The only way to do this properly is using generics like this:
public interface A<T> where T : A<T>
{
T method1();
}
Then B looks like this:
public interface B : A<B>
{
void otherMethod();
}
And finally, implementing a class would go like this:
public class Bravo : B
{
public B method1() { return null; }
public void otherMethod() { }
}
However, you can use the new keyword to shadow a method in an interface, but this isn't a great idea as it makes it harder to reason about your code as it breaks normal inheritance.
Try this:
public interface A
{
A method1();
}
public interface B : A
{
new B method1();
void otherMethod();
}
public class Bravo : B
{
A A.method1() { return null; }
public B method1() { return null; }
public void otherMethod() { }
}
That sure is possible, use the new keyword here, not the override and implement the overridden interface explicitly.
Edit:
Adjusted the sample based on your comments. You will still need the explicit interface implementation IFoo IFoo.GetData() { return GetData(); }, but this one has no code on its own, since its just calling he implicit implementation public INewFoo GetData() { return new Foo(); }.
Here is an example:
public interface IFoo
{
IFoo GetData();
}
public interface INewFoo : IFoo
{
new INewFoo GetData();
}
public class Foo : INewFoo
{
IFoo IFoo.GetData() { return GetData(); }
public INewFoo GetData() { return new Foo(); }
}

Implementing interface correctly in C# BOL classes

I've been searching for a bit and found similar things but nothing that quite answers my question. Here it is- I have two classes. A, B. I want class C to have all the properites of those two classes. This is in the Object Layer, c#.net.
Class A:
public class A
{
public string property1 { get; set; }
}
public class B
{
public string anotherproperty { get; set; }
}
public interface IB
{
B b { get; set; }
}
public class C : A, IB
{
//nothing here cause hopefully it inherits everything
}
I have no idea if my implementation is even close. I do get error message of "C does not implement interface member IB"
Anyone know how to do this?
I have two classes. A, B. I want class C to have all the properites of those two classes.
...then you will have to manually add either A's or B's properties to C. C# does not support multiple inheritance, sorry.
However, in most cases multiple inheritance is not needed. A common alternative is to use composition instead of inheritance: For example, you could have your class C provide references to instances of A and B:
public class C
{
private A a = new A();
private B b = new B();
public A A { get { return a; } }
public B B { get { return b; } }
}
This would allow you to access all properties via myC.A.property1 and myC.B.anotherproperty.
If you really need to combine implementations from both A and B in C, you might need to have a look at Mixin libraries for C#.
You can do something like this:
public class ClassA
{
public string AProp { get { return "AProp";} }
}
public class ClassB : ClassA
{
public string BProp { get { return "BProp"; } }
}
public class ClassC : ClassB
{
}
And then:
ClassC c = new ClassC();
Console.WriteLine(c.AProp);
Console.WriteLine(c.BProp);
Prints:
AProp
BProp
You can't override anything but you can access the inherited properties.

Can you attach an interface to a defined class

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);
}
}

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;
}
}

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