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

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

Related

C# Way to enforce all classes have a method of a given name

I am not sure if this even makes sense hence asking it widely.
Is it possible for enforce that a set of classes always implements a function with a given name. The method in each class might have different signature - but should have the same name. Some like below:
public class ClassOne {
public int GetSomething (int a, int b, out int c) { }
}
public class ClassTwo {
public int GetSomething ( int a, out string b) {}
}
I want anyone who writes ClassThree or ClassFour as part of this library to implement the GetSomething method. Is there a C# construct that allows one to enforce this?
Not looking at design review of this - just want to know if its possible at all without manually enforcing via code reviews.
You can't do that with out-of-the-box C#. C# has abstract classes and interfaces, but they require a specific signature for a method, not just a name.
You could get this working by creating code analyzers in Roslyn, where you check your code if it has the required method.
However, I don't think you should all this. I think you are making a design flaw here in requiring a method with a specific name, without forcing the arguments of it.
You could always implement a method similar to the Main method found in every C# application. It uses a string[] as parameter where you can put a number of variables in. In your case I would opt for an object[]. However, this design has its flaws too obviously.
What is the purpose of a class with method of unknown arguments. It is just illogical in terms of OOP. How are you going to call this method? If arguments are homogeneous then you could just do something like:
public interface IBaseInterface
{
public int GetSomething(Dictionary<string, object> args); // keys matter
}
or
public interface IBaseInterface
{
public int GetSomething(params object[] args); // order matters
}
In some cases Func<> / Action<> high-order functions may be useful.
If you provide a usage case, we would be able to make a more precise answer.
Show how you are going to call such method and I will try to show how to make it better.
Answering your question only from technical side, you could do the following:
public abstract class BaseClass
{
protected BaseClass()
{
if (this.GetType().GetMethod("GetSomething") == null)
throw new InvalidOperationException("BaseClass subclasses should implement 'GetSomething' method");
}
}
public class ClassOne : BaseClass {
public int GetSomething (int a, int b, out int c) { }
}
public class ClassTwo : BaseClass {
public int GetSomething (int a, out string b) {}
}
It will not guarantee this behavior at design-time, but will ensure that such methods exists at run-time.
Add an interface with the method you want.
Set classes inherit from this interace
interface ISampleInterface
{
void SampleMethod();
}
class ImplementationClass1 : ISampleInterface
{
// Explicit interface member implementation:
void ISampleInterface.SampleMethod()
{
// Method implementation.
}
}
How about encapsulating parameters in a "Criteria" object?
public interface IGettable
{
int GetSomething (Criteria crit);
}
public class Criteria
{
public CriteriaType type {get; set;};
public int a {get; set;};
public int b {get; set;};
...
public static Criteria ClassOneCriteria(int a, int b)
{
return new Criteria
{
type = CriteriaType.ClassOneCriteria,
a = a,
b = b
}
}
...
}
public enum CriteriaType
{
ClassOneCriteria,
ClassTwoCriteria
}
public class ClassOne : IGettable
{
public int GetSomething (Criteria crit)
{
if (crit.type != CriteriaType.ClassOneCriteria)
throw new Exception("Invalid criteria type for Class One");
...
}
}

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.

C# Return Type should this.getType()

I have a Function in C# and it have to return the type of the Class. Also in subclasses which extends the class.
Like:
public class A
{
public typeof(this) Method()
{
//Code
}
}
public class B : A {
public override typeof(this) Method() {
//Code
}
}
So the Method in class A should have the return type A. And the Method in class B should have the return tpye B.
Is there a way to do it?
No, this isn't possible. What you're asking for is called a covariant return type, but C# doesn't support this. The closest you can get is either this:
public class A
{
public virtual A Method()
{
//Code returning an A
}
}
public class B : A
{
public override A Method()
{
//Code returning a B
}
}
Which is legal because every B is also an A, or you can use generics instead of inheritance:
public class Foo<T>
{
public virtual T Method()
{
//Code
}
}
And then you can have Foo<A> and Foo<B> -- however, Foo cannot depend on any specifics of T. You can combine this with inheritance, which will sort of achieve what you want:
public class A : Foo<A>
{
// And now A has a Method that returns A
}
public class B : Foo<B>
{
// And now B has a Method that returns B
}
But the problem with this approach is that you will have a hard time actually implementing Method in a meaningful way, because in Foo you cannot use anything specific to the type. To make this explicit, you could make Method abstract:
public abstract class Foo<T>
{
public abstract T Method();
}
public class A : Foo<A>
{
public override A Method()
{
// Code
}
}
public class B : Foo<B>
{
public override B Method()
{
// Code
}
}
I'm having a hard time imagining a scenario where you can actually make use of this, but at least it meets the requirements.
Last but not least, you are not required to use inheritance -- does B really need to derive from A or could you inherit from some common base that does not use Method?
Depending on what your method is trying to do, it might be possible to achieve what you want by using extension methods.
public class A { }
public class B : A { }
public static class AExtension {
public static T Method<T>(this T target) where T: A {
// do your thing here.
return target; // or, return a new instance of type T.
}
}
You can then call Method() and let C# infer the generic argument:
var a = new A();
a = a.Method(); // C# will infer T as A.
var b = new B();
b = b.Method(); // C# will infer T as B.
The downside to this approach is, of course, that you cannot access non-public members of your classes in Method(), unless you use reflection.
There is a way to do this, actually.
class A {
public A Method () { ... return this; }
}
class B : A {
new public B Method () => (B)base.Method();
// or { base.Method(); return this; }
}
Make sure you only use this if you know that the base returns this.

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

Making a generic copy method with extensions

Context: this is for an engine, which is full of generic classes so that future users can extend certain parts of the behavior without concerning themselves with the inner workings of the engine itself.
Right now, I need a class C:
public class C
{
public C Copy(params) { ... }
}
But also an extension class D:
public class D : C
{
public D Copy(params) { ... }
}
Basically I have some generic classes, but I need a copy method (actually it's a "make a copy at a new location" method, but that's immaterial) which returns the right type.
public class SampleClass<T>
where T : C
{
public void Stuff()
{
...
T copy = favoriteThing.Copy(params);
...
}
}
and etc. I could just cast it, and trust future implementers to get it right, but I'd rather make it all explicit with contracts. Are there any elegant ways to do this?
One way might be to define an ICopyable<T> interface that's implemented by C and D:
public interface ICopyable<T>
{
T Copy(params);
}
public class C : ICopyable<C> { ... }
public class D : C, ICopyable<D> { ... }
Now if SampleClass<T> constrains T to ICopyable<T>, it can call Copy and get back an object of type T without any casts:
public class SampleClass<T>
where T : C, ICopyable<T> // added constraint
{
public void Stuff()
{
T favoriteThing = ...
...
ICopyable<T> copyable = favoriteThing;
T copy = copyable.Copy(params); // no cast needed
...
}
}

Categories

Resources