C# generics - Can I make T be from one of two choices? - c#

Suppose I have the following class hierarchy:
Class A {...}
Class B : A {...}
Class C : A {...}
What I currently have is
Class D<T> where T : A {...}
but I'd like something of the form
Class D<T> where T in {B,C}
This is due to some odd behavior I'm not responsible for where B and C have common methods which aren't in A, but it would be nice to be able to call them in D on T.
Note: I don't have access to A,B or C to edit them

You need to define an interface for the common methods that are in B and C (lets call it Ibc), make B and C implement this interface, and then you can write:
Class D<T> where T : A, Ibc {...}

This isn't directly possible.
As others suggest, you could define an interface and implement it in both B and C.
If this isn't an option (e.g., if these classes are beyond your control), what I might suggest is this: first, start with an abstract class that includes all the functionality you can achieve with any T deriving from A. Then say you have some methods that exist for both B and C that aren't a part of A. In D you can make these abstract methods to be implemented by subclasses:
public abstract class D<T> where T : A
{
protected T _member;
public void DoSomethingAllTsCanDo()
{
_member.DoSomething();
}
public abstract void DoSomethingOnlyBAndCCanDo();
}
Then you can inherit from the base class for each type B and C and override the abstract method(s) to provide the appropriate functionality:
public class DB : D<B>
{
public override void DoSomethingOnlyBAndCCanDo()
{
_member.DoSomethingOnlyBCanDo();
}
}
public class DC : D<C>
{
public override void DoSomethingOnlyBAndCCanDo()
{
_member.DoSomethingOnlyCCanDo();
}
}

First, If B and C have common methods, it is a design flaw they don't share an interface. That said, you can fix that even without having access to B and C.
It is possible to create a common interface. Suppose you have:
public class A
{
}
public class B : A
{
public void Start() { }
}
public class C : A
{
public void Start() { }
}
You can create a common interface:
public interface IStartable
{
void Start();
}
And use it on derived classes from B and C:
public class BetterB : B, IStartable
{
}
public class BetterC : C, IStartable
{
}
You may not be able to achieve that if you get B and C instances as is, but it can be considered if you create them. In fact, with specialized classes of B and C, you may use the interface instead of D<T>.

Do B and C implement the same interface? That may be a better route.

Some options:
Make an interface IderivedFromA that contain the common methods from B and C.
Looks like this is impossible from your question
In D cast T to dynamic and call the methods dynamically
The most easy solution, if you can use .Net 4
In D test if the you deal with an B or C, cast, and call
Will be checked by the compiler, and is possible from .Net 2
The Dan Tao answer: Create a specific implementation of D<T> for B and C, these can call the methods from B and C directly. (Didn't think of this one myself).
Will only work if the "user-source" knows it is dealing with B or C, and does not use the abstract A to use D<A>. Instead it should use DB or DC. But I think this is the case, otherwise you didn't need generics.

The where constrain in C# does not allow you to specify multiple classes as a choice.
Also if you will specify multiple where contains, then they both has to be satisfied. There is no OR logic for constrain.
Here is specification: http://msdn.microsoft.com/en-us/library/bb384067.aspx
Answers from Grzenio seems right for you. Extract common behavior into the common interface for B and C. Then you can use that interface as a constrain.

Since you don't have access to the source, the only real answer (unless you are willing to lose safety by using dynamic) is explicitly check for B/C and cast.

Related

Generic type constraint for significant classes

Is it possible to define generic constraint for multiple classes that doesn't share a base class/interface?
For ex.
class A
{
}
class B
{
}
class C
{
void Test<T>(T someObj)
{
...
}
}
I want to pass either class A or B to Test method, nothing else.
I know that I can put a where statement with the base class/interface of A or B but I can't specify base interface/class for the related classes in my situation.
No, and it doesn't make sense to do so. It isn't a generic any more. If class A and B share properties, methods, etc, they should share the same interface or base class. If not, they are not 'the same' and can't be treated as such.
Guess what would happen if you changed the method signature in one of the two classes. Suddenly that method isn't 'shared' any more. The compiler doesn't try to determine what methods and properties can be considered shared, instead it doesn't support the feature you request.
An option would be to use two methods (one overload of every type) which introduces repeating code, which is bad of course. It would be better to use an interface, or if it is really out of you hands dynamic, although I try to minimize the use of it.
No this is not possible in compile time.
If it would be, how would you use the generic parameter type T? Would it behave like A or like B?
Consider the following:
class A
{
public void MethodInA();
}
class B
{
public void MethodInB();
}
class C
{
// pseudocode here!
void Test<T>(T someObj) where T : A or B
{
// how it would behave if T is B?
someObj.MethodInA();
// how it would behave if T is A?
someObj.MethodInB();
}
}
Instead extract some base class or interface, that will be common for both A and B classes and use it in your generic method constraint.
If there's nothing shared, then:
void Test(A obj) {}
void Test(B obj) {}
is the only real way to do it. You could make the generic method private, and the overloads public, and just call the private method from the overloads, as in:
private void TestImplementation<T>(T object) { ... }
public void Test(A obj) { this.TestImplementation(obj); }
public void Test(B obj) { this.TestImplementation(obj); }

c# behavior on interface implementation

I've found a behaviour in c# and I would like to know if it's in the specs (and can be expected to work on all platforms and new versions of the .NET runtime) or if it's undefined behaviour that just happens to work but may stop compiling at any time.
So, let's say I want to take existing classes, like these:
public class HtmlTextBox
{
public string Text {get; set;}
}
public class HtmlDiv
{
public string Text {get; set;}
}
now I would really like them to implement a common IText interface, like this one:
public interface IText
{
string Text {get; }
}
but I can't change the classes directly because they are part of an external library. Now there are various ways to do this, through inheritance or with a decorator.
But I was surprised to find out that doing simply this compiles and works on .NET 4.5 (windows 7 64 bits).
public class HtmlTextBox2 : HtmlTextBox, IText {}
public class HtmlDiv2 : HtmlDiv, IText {}
That's it. This gets me drop-in replacements for HtmlTextBox and HtmlDiv that use their existing Text property as implementation for IText.
I was half-expecting the compiler to yell at me, asking me to provide an explicit re-implementation of Text, but on .NET 4.5 this just works:
IText h2 = new HtmlTextBox2{Text="Hello World"};
Console.WriteLine(h2.Text); //OUTPUT: hello world
In fact,I've tried the same on mono (whatever version ideone.com is using) and mono does not yell at me either
So I guess I'm good to go, but before trying this on serious code I wanted to check if I've misunderstood what is really happening here or if I can't rely on this to work.
Yes, this is expected behavior. The implementation of an interface's method needs not to be done in the class where the interface is actually applied; it can be in any ancestor class.
The C# Language Specification 5.0 documents this in section 13.4.4; excerpt of the rule:
The implementation of a particular interface member I.M, where I is the interface in which the member M is declared, is determined by examining each class or struct S, starting with C and repeating for each successive base class of C, until a match is located
Some clarification to my comment
Yes, that should indeed just work as intended. An interface defines what methods a class should implement (either directly or throughout the hierarchy).
When you define an interface, you could look at it like this:
An interface's only task is to guarantee that at any point in a class' hierarchy where the interface is defined in the signature, that class has every method in the interface implemented.
Here's a sample situation that hopefully sheds some light:
void Main()
{
Z obj1 = new C();
Z obj2 = new B();
Z obj3 = new A();
Y obj4 = new C();
Y obj5 = new D();
Z obj6 = new D();
}
interface Y {
void someMethod1();
void someMethod2();
}
interface Z {
void someMethod3();
}
class A : Z {
public void someMethod3() { }
}
class B : A {
public void someMethod1() { }
}
class C : B, Y {
public void someMethod2() { }
}
class D : C { }
This compiles just fine.
As you can see, B implements Y's method someMethod1 after which C extends B and implements Y. All C does is provide an implementation for someMethod2 and at that point the interface definition is reached: the two methods that are defined in Y are now available to an object of type C.
What's key here is to remember that a class hierarchy are just layers with, amongst others, some methods. At the moment in a hierarchy where you say "this class needs to implement every method defined in <SomeInterface>" you basically have to make sure that each of them is available to your class at that point. Inheritance tells us that we can use the methods of a superclass, which means that by implementing your method in a baseclass you have satisfied the condition.
Sidenote: all of this is written without abstract methods in mind, they're a little different.

Virtualism Inherited in C#

I picked this code form MSDN resources in C# polymorphism.
public class A
{
public virtual void DoWork() { }
}
public class B : A
{
public override void DoWork() { }
}
public class C : B
{
public override void DoWork()
{
// Call DoWork on B to get B's behavior:
base.DoWork();
// DoWork behavior specific to C goes here:
// ...
}
}
It says class C is overriding the DoWork() of B, but the DoWork() method of class B is not made virtual. Since C inherits all methods and data of B, does it also inherit the virtual methods of A (which are available in B, as A is the base class for B)?
What if B does not provide an implementation of DoWork() then would C be accessing the copy of A's virtual method directly to override it?
Also, when C inherits from B does it get a separate copy of A's members or the copy of those of B.
I guess for separate copy of A's members one has to inherit A separately, like
public class C : A, B
Correct me if wrong.
EDIT :
public class A
{
public virtual void DoWork()
{
Console.WriteLine("In Class A");
}
}
public class B : A
{
public void DoWork() { Console.WriteLine("In Class B"); }
}
public class C : B
{
public void DoWork()
{
Console.WriteLine("In Class C");
base.DoWork();
}
}
When I run this on VS C#, virtual keyword is not reqd. in class B's DoWork(), and override keyword in class B's and C's DoWork(), as it generates only a tip-off warning. So does it mean just specifying which base class is being derived in the class name definition as in public class C : B is enough to qualify he methods o be virtual in nature?
Also, since C# doesnot provide with the option of multiple inheritance of classes, is there a way to directly use A's implementation of DoWork() from C's class without explicitly creating an object of A and then accessing DoWork() using it?
It says class C is overriding the DoWork() of B, but the DoWork() method of class B is not made virtual.
When you override a virtual method, it "stays" virtual unless you explicitly seal it with sealed. (You can only specify the sealed modifier for a method if it's also an override method.)
What if B does not provide an implementation of DoWork() then would C be accessing the copy of A's virtual method directly to override it?
Yes. Or rather, it would invoke A's implementation at execution time. It's not really a "copy".
Also, when C inherits from B does it get a separate copy of A's members
It's not really clear what you mean here. What sort of "copy" are you talking about, and which members? If you mean which fields are in each object, then it's just the union of the fields declared in all the classes up the inheritance chain.
EDIT: In your edited code, you're not overriding anything. You're declaring new methods, which aren't called polymorphically. So if you write:
A a = new C();
a.DoWork();
that will just print "In Class A" - whereas if B and C overrode the virtual method, it would print "In Class C" and then "In Class B".
Also, since C# doesnot provide with the option of multiple inheritance of classes, is there a way to directly use A's implementation of DoWork() from C's class without explicitly creating an object of A and then accessing DoWork() using it?
Assuming this is in the case where B overrides DoWork, no. That would break encapsulation - it could break the invariants of B, for example.
C is inheriting from B, this means it can override all virtual methods in B. Override means method is still virtual.
If B would not give any implementation for DoWork, then base.DoWork in C's implementation would call the implementation in A class - as normally virtual behaves. You should not assume that your base call will be call to exactly B method and no other - it's implementation detail that could be changed in future. Important thing is it will call nearet parent implementation of DoWork.
And finally - when inheriting B, you also get all the properties, methods and everything inherited from A. In C# there is nothing like multiple inheritance (meaning C : A, B where C, A and B are classes will not work). You cannot get separate copy or anything of A with inheritance - you just get what's in B (which of course includes things that B has inherited from A and so on).

Exposing different interfaces from single class

We are trying to build some kind of a layer above the DAL in order to expose an interface of a certain repository methods using generics.
For example:
public interface A
{
void Do_A();
}
public interface B
{
void Do_B();
}
public void Main()
{
Exposer<A>.Do_A();
Exposer<B>.Do_B();
}
Is it possible to do that ?
Tecnically, that isn't a "single class", since Exposer<A> is a different Type to Exposer<B>; however, ultimately, this doesn't look much different to most IoC/DI containers... if this was, say, StructureMap (purely for an example), you might consider:
container.GetInstance<A>().Do_A();
container.GetInstance<B>().Do_B();
you would, of course, need to configure the container to know where the concrete A and B implementations are coming from! Which for StructureMap is shown here, but there are plenty to choose from.
If you mean directly, then: no. You cannot have:
class Exposer<T> : T {...} // non-working code to implement the interface T
You can, however, have some class:
class Exposer : A, B {...}
and just cast:
A a = Exposer;
a.Do_A();
B b = Exposer;
b.Do_B();
A type Foo<T> cannot implement (or extend) the actual T, as T is unknown at compile time. What you could do is expose a T as a property, and invoke methods on it. However, as Ondrej wrote, the question may be a little unclear.
Are you describing IoC when you write?
Exposer<A>.Do_A();
Your Exposer class makes me think to StructureMap API:
ObjectFactory.GetInstance<T>().Do_A();
If you want to get rid of the keyword new and get in a generic way an instance for a specified interface, take a look to this article or check StructureMap
To choose which interface implementation you want when consuming a given class, you don't use generics, you just cast the class to the interface:
public interface A
{
void Do_A();
}
public interface B
{
void Do_B();
}
public class Exposer : A, B
{
public void Do_A() { ; }
public void Do_B() { ; }
}
public void Main()
{
// the casts are redundant here,
// because the interface implementation
// is implicit
((A)Exposer).Do_A();
((B)Exposer).Do_B();
}
If you want to exclude members that are not implementations of members of the given interface, use explicit implementation:
public class Exposer : A, B
{
void A.Do_A() { ; }
void B.Do_B() { ; }
}
public void Main()
{
// the casts are now required;
// otherwise, you'll get a compiler error
// telling you that the method is inaccessible
((A)Exposer).Do_A();
((B)Exposer).Do_B();
}

.net abstract override quirk

Lets say i have the following c# classes:
abstract class a
{
protected abstract void SomeMethod();
}
abstract class b : a
{
protected abstract override void SomeMethod();
}
class c : b
{
protected override void SomeMethod()
{
}
}
Is there actually any point in overriding the method in b when it could just as easily be writen as:
abstract class b : a
{
}
What would be the "prefered" way of writting b? And if there is no point overriding an abstract method or property why is it allowed?
One reason you might want to allow it: it shows intent. It explains that yes, you know this method is abstract in the base class. I know that, and I still want it to be abstract here.
That way, if the base class removes the method, your abstract class will fail to compile, rather than only the concrete class (which may not even be in your code).
That said, it's not a particularly important reason... I'd normally leave it out.
Additional to the already said:
override could also be used to declare attributes that are not defined in the base class. If still not having an implementation, it will be an abstract override.
abstract class b : a
{
[SomeAttribute]
protected abstract override void SomeMethod();
}
I normally don't re-declare abstract methods when I don't actually intend to supply an implementation - for several reasons:
I doesn't change the semantics of your code.
It adds one more thing to refactor if the base class changes.
It leads to inconsistency of new abstract methods are added to the base class and you don't add them to intermediate classes.
It's quite painful to do so in a class hierarchy with more than a few levels.
It clutters your code with declaration that add little value.
Have a look at this blog. Sometimes combining both is useful:
"Good language design usually results
in a few well defined simple
primitives that can be combined
together in intuitive and intelligent
ways. In contrast, poor language
design usually results in many bloated
constructs that don't play well
together.
The "abstract" and "override" keywords
in C# are a great example of this.
They both have simple definitions, but
they can be combined to express a more
complex concept too.
Let's say you have a class hierarchy:
C derives from B, and B derives from
A. A has an abstract method Foo() and
Goo(). Here are 2 scenarios where
"abstract override" would come up. 1)
Let's say B only wants to implement
Goo(), and let C implement Foo(). B
can mark Foo() as "abstract override".
This clearly advertises that B
recognizes Foo() is declared in the
base class A, yet it expects another
derived class to implement it.
2) Let's say B wants to force a C to
reimplement Foo() instead of using A's
definition of Foo(). B marks Foo() as
both override (which means B
recognizes Foo() is declared in the
base class) and abstract (which means
B forces derived class C to provide an
implementation; regardless that A
already provided an implementation).
This came up in one of my recent blog
entries here. In that example,
A=TextReader, Foo=ReadLine, B= a
helper class, C=some class that wants
to implement ReadLine() instead of
Read(). Now TextReader already has a
default implementation of ReadLine()
based on Read(), but we want to go the
other way around. We want an
implementation of Read() based off a
derived classes implementation of
ReadLine(). Thus B provides an
implementation of Read() that consumes
ReadLine(), and then marks ReadLine()
as "abstract override" to force C to
redefine ReadLine() instead of picking
up the one from TextReader.
In summary, "abstract override" is
cool not because it's yet one more
language feature to express some
complex corner case; it's cool because
it's not one more language feature.
The neat part is that you don't really
need to think about any of this. You
just use the individual basic concepts
naturally, and the complicated stuff
comes together automatically."
This is my example code for scenario 1:
public abstract class A
{
public abstract void Foo();
public abstract void Goo();
}
public abstract class B : A
{
public abstract override void Foo();
public override void Goo()
{
Console.WriteLine("Only wanted to implement goo");
}
}
public class C : B
{
public override void Foo()
{
Console.WriteLine("Only wanted to implement foo");
}
}
And my sample code for scenario 2:
public abstract class A
{
public virtual void Foo()
{
Console.WriteLine("A's Foo");
}
public abstract void Goo();
}
public abstract class B : A
{
public abstract override void Foo();
public override void Goo()
{
Console.WriteLine("Only wanted to implement goo");
}
}
public class C : B
{
public override void Foo()
{
Console.WriteLine("Forced to implement foo");
}
}
In your question the code is not that useful, but that doesn't mean that abstract and override combined is not useful.
You should not need to override SomeMethod() in b. An abstract class declares that there can be undefined/abstract methods in it. When you extend one abstract class with another, it implicitly inherits any abstract methods from the parent.

Categories

Resources