Generics c#.net - c#

In the below code "where T : WsgTypes.RouteRestriction", can I add multiple classes so that T can be of only those few classes types which I am interested of
public static T GetDetails<T>(string code) where T : WsgTypes.RouteRestriction
{
T details;
if (typeof(T) == typeof(WsgTypes.TicketType))
{
details = TicketTypeDetail.GetDetails(code) as T;
}
else if (typeof(T) == typeof(WsgTypes.RouteRestriction))
{
details = RouteRestrictionDetail.GetDetails(code) as T;
}
else
{
throw new NotSupportedException("");
}
return details;
throw new NotImplementedException();
}

It seems to me that this isn't a proper use of generics. It would be better if TicketType and RouteRestriction implemented some IDetailed.

No, generic type constraints can only specify a single base-class.
You can specify multiple interfaces, but this is "all of", not "any of".
What you ask is possible with overloading, but not with generics.

For inheritance you can have a single class with multiple interfaces.
public static T GetDetails<T>(string code) where T : WsgTypes.RouteRestriction, , IComparable
{
}
Instead you can have an interface and have multiple classes implementing it.
public interface IInterface
{}
public class Class1: IInterface
{}
public class Class2: IInterface
{}
public static T GetDetails<T>(string code) where T:IInterface
{
T instance;
// ...
return instance;
}

I'm afraid you can't. The usual way is to provide a common interface that all classes you're interested in implement. The problem is that, inside the generic body, the compiler expects a generic type parameter to be unambigous.
Well, or you could take an object as parameter and cast it at your will. But... no. Don't.
Note that instead of typeof, you could also use the is and as operators.

See this article...
http://msdn.microsoft.com/en-us/library/d5x73970.aspx
... for more information on constaints. You can add multiple constraints, and you can constrain by some interface or by some base class, but not by a list of arbitrary classes.
Here's an example of multiple constraints (from the above):
class Base { }
class Test<T, U>
where U : struct
where T : Base, new() { }

Did you try separating them like this:
public static T GetDetails<T>(string code) where T : WsgTypes.RouteRestriction, NextClass, AnotherClass, AndSoOn
{
...
}

Related

How can a class inherit from a parameterized version of itself?

I saw a C# class SomeClass that was defined like
public class SomeClass : IComparable<SomeClass>, IEquatable<SomeClass>
{
// ...
}
and I'm wondering how to translate that into English. The way I understand it seems logically impossible. How can a class inherit from a parameterized version of itself? Also, is this a common design pattern?
The key is to recognize that it's not inheriting from (or implementing) a parameterized version of itself, but rather inheriting from (or implementing) another class or interface, and using itself as a generic parameter for that target type.
For example, IComparable<T> says that there will be a CompareTo() method that takes an object of type T as a parameter. So by implementing IComparable<SomeClass> you're simply guaranteeing that a method with that signature will exist on this class:
public class SomeClass : IComparable<SomeClass>
{
public int CompareTo(SomeClass other)
{
//...
}
}
And yes, this is fairly common practice. Classes often implement the generic IComparable<> and IEquatable<> interfaces to show that they can be compared with other items of the same type. It's maybe also worth mentioning that enums in Java are declared as extending Enum<> of themselves--a pattern which is not common in C#, but does appear from time to time.
Translated in "English" it means: "Boy (or girl), you'd better be type-safe when implementing those interfaces, especially IComparable. Otherwise, you'll have to perform type casting, which I guess you don't want"
See the code below. SomeClass implemented IComparable and IComparable.
See differencies between implementations of CompareTo(object) and CompareTo(SomeClass).
namespace InterfacesStuff
{
internal class Program
{
private static void Main(string[] args)
{
var someClass1 = new SomeClass {ComparedValue = 1};
var someClass2 = new SomeClass {ComparedValue = 2};
//someClassObject defined as SomeClass
//object someClassObject = new SomeClass { ComparedValue = 2 };
//someClassObject defined as anything else but SomeClass
object someClassObject = 5;
int comparisonSomeClassBySomeClass = someClass1.CompareTo(someClass2);
int comparisonSomeClassByObject = someClass1.CompareTo(someClassObject);
}
}
public class SomeClass : IComparable, IComparable<SomeClass>, IEquatable<string>, IEquatable<int>,
IEquatable<double>
{
public int ComparedValue;
public int CompareTo(object obj)
{
var presumedSomeClassObject = obj as SomeClass;
if (presumedSomeClassObject != null)
{
if (ComparedValue <= ((SomeClass) obj).ComparedValue)
return -1;
}
return 0;
}
public int CompareTo(SomeClass other)
{
if (ComparedValue <= other.ComparedValue)
return -1;
return 0;
}
public bool Equals(double other)
{
throw new NotImplementedException();
}
public bool Equals(int other)
{
throw new NotImplementedException();
}
public bool Equals(string other)
{
throw new NotImplementedException();
}
}
}
It is not Inheriting, It is implementing the IComparable Interface. what is going on is
Someclass Implements the Icomparable and the IEquatable interface. Implementing an interface is like signing a contract stating you gaurentee that this class will implement the methods on an interface.
Icomparable msdn, IEquatable. If you look at the MSDN pages you can see that SomeClass gaurentees it will implement the methods in some fashion.
This is very common practice and it is many different names. The ones I hear most are programming by contract and Implementation over Inhertience. It lets you do a lot of cool things, like Dependency Injection, Proper Unit testing, better Generics. It does this because the compiler doesnt need to know the concrete class that your object is implementing. It just needs to know that it has certain functions on it. For further reading on this I would read Chapter one of the gang of four Design pattern book.
Wikipedia link Specifically the Introduction to Chapter one section
It doesn't really have to be convenient to express it in english for it to be valid code, although I'd probably read that as "SomeClass is comparable and equatable to itself". That doesn't really explain what's going on though, it's just a way of expressing it.
In C# types can be generic over categories of other types. Generic types are basically "type constructors". They take other types as parameters, and use them to construct new types. For instance, IEnumerable<int> and IEnumerable<string> are two completely different types. The non-generic version (IEnumerable) is a third one. In C# a type A can inherit ANY other type B as long as none of the following is true (I hope I didn't miss anything):
B is already a subtype of A
B is a class and A has already inherited another class
B is a struct
A is an interface but B is not
A is the same type as B
B is sealed
A is a struct and B is not an interface
This even makes the following code legal:
class Foo<T>
{
public T Value;
}
class Foo : Foo<int>
{
}
Foo and Foo<T> are different types, so there's no problem at all for one to inherit the other.
You can read more about generics here:
https://msdn.microsoft.com/en-us/library/ms379564(v=vs.80).aspx
And about inheritance here:
https://msdn.microsoft.com/en-us/library/ms173149.aspx
The code you posted does not inherit from any class. It is implementing certain so-called Interfaces. How to translate that snippet: "I guarantee that SomeClass will be Comparable and equatable with other SomeClass instances. I will provide definitions in this class on how to do that."
About specializing a class from some other class...
What you can do is something like this:
using System;
using System.Collections.Generic;
namespace ConsoleApp1
{
class Pet
{
protected string name;
public Pet(String name)
{
this.name = name;
}
}
class Dog : Pet
{
private List<String> tricks;
public Dog(String name, List<String> tricks):base(name)
{
this.tricks = tricks;
}
}
class Program
{
static void Main(string[] args)
{
List<string> tricks = new List<string>();
tricks.Add("sit");
tricks.Add("jump");
tricks.Add("bark");
Dog puppy = new Dog("Fido", tricks);
}
}
}
Dog inherits from Pet. Dog calls Pet's constructor at creation. Whatever name you pass into Dog constructor, it will forward it to Pet constructor.
Because what happens is that a subclass first calls the constructor of its superclass with the appropriate arguments. Then it runs its own constructor. Whatever is declared as public or protected in a class will be visible to its subclasses.
Therefore Dog will have name and also a list of tricks:
You achieve this kind of view with the "Locals" window.
I recommend that you read some tutorials on c# inheritance, interfaces and generics

Overriding (shadowing, overloading?) methods with different return types in a C# hierarchy

I'm writing an SDK which has an OOP structure for implementing data types;
first an interface
then an abstract implementation
finally an abstract generic implementation
People can choose to implement either the interface, or derive from either of the classes.
public interface IGoo
{
IGoo Duplicate();
...
}
public abstract class Goo : IGoo
{
IGoo IGoo.Duplicate() {
return Duplicate();
}
abstract public Goo Duplicate();
...
}
public abstract class Goo<T> : Goo
{
abstract public Goo<T> Duplicate(); ??????
...
}
I'd like to re-implement the Duplicate method so that it always returns the most specific type possible. I.e. when you call Duplicate on an IGoo instance, you get another IGoo. If you call it on Goo, you get Goo, if you call it on -say- Goo<int>, you get Goo<int>. And all Duplicate() methods always call the most specific implementation.
Is this possible? Is it only possible when you can implement an interface explicitly? In which case, should I not make Goo<int> derive from Goo, but have it implement IGoo instead and type all the low-level functionality twice?
What about the following?
public interface IObj
{
IObj Duplicate();
}
public abstract class Obj : IObj
{
public Obj()
{
}
public virtual IObj Duplicate()
{
return this;
}
}
public abstract class ObjT<T> : Obj
{
public ObjT()
{
}
public override IObj Duplicate()
{
return this;
}
}
public class ObjImpl : Obj
{
}
public class ObjTImpl : ObjT<int>
{
}
I understand that you want it to return the most specific type possible in any inheriting class but it actually is. It's boxing the inheriting type into the interface (or a raw object if you where to return objects instead of interface types. If you run the following test in a console app you will see the proper type is represented:
namespace TestConsole
{
class Program
{
static void Main(string[] args)
{
ObjImpl a = new ObjImpl();
ObjTImpl b = new ObjTImpl();
Console.WriteLine(a.Duplicate().GetType());
Console.WriteLine(b.Duplicate().GetType());
Console.ReadLine();
}
}
}
// outputs:
// ObjImpl
// ObjTImpl
The idea of redefining abstracts of abstracts goes against the purpose of abstract polymorphism. If the derived types do not intend to implement the inherited abstract member, they should not be inheriting it.
Although the example I gave above would require casting to access any child class-specific members, it would be the proper way to do it in this approach. The runtime needs to know what types it should expect to deal with.
There is always dynamics you could play around with but to be honest I haven't played around with dynamics with generics and inheritance as I suspect I would make my compiler cry, and when it cries, I cry, a little bit deep down inside... lol
It is only possible when you implement the interface explicitly. That's because the return type of a method is not part of its signature - which the compiler checks when overloading. Therefore, otherwise identical methods which only differ in their return type are syntactically not possible.

C# covariance and inheritance

I'm curious to know why the implementation of my interface in the abstract base class does not satisfy the the requirements in sub-classes. Here's an example:
public interface IBase { }
public interface IConcrete : IBase { }
public interface IBaseManager<out T>
where T : IBase
{
T Create();
IEnumerable<T> SelectAll();
}
public interface IConcreteManager : IBaseManager<IConcrete> { }
public abstract class Base : IBase { }
public class Concrete1 : Base, IConcrete { }
public abstract class BaseManager<T> : IBaseManager<T> where T : class, IBase
{
#region IBaseManager<T> Members
public T Create()
{
throw new NotImplementedException();
}
public IEnumerable<T> SelectAll()
{
throw new NotImplementedException();
}
#endregion
}
public class ConcreteManager : BaseManager<Concrete>, IConcereteManager
{
//error occurs here
}
This is the error that is being generated:
'ConsoleApplication4.ConcreteManager' does not implement interface member 'ConsoleApplication4.IBaseManager<ConsoleApplication4.IConcrete>.Create()'.
'ConsoleApplication4.BaseManager<ConsoleApplication4.Concrete>.Create()' cannot implement 'ConsoleApplication4.IBaseManager<ConsoleApplication4.IConcrete>.Create()' because it does not have the matching return type of 'ConsoleApplication4.IConcrete'.
If I add these methods to the ConcreteManager class, everything is fine and the compiler is happy.
public new IConcrete Create()
{
return base.Create();
}
public new IEnumerable<IConcrete> SelectAll()
{
return base.SelectAll();
}
If simply returning what the methods from the base class return is sufficient, why do the methods have to be added? Why can't the compiler call the methods in the base class?
As John points out correctly, the C# language does not support return type covariance. Neither does the CLR, so even if the language supported it, the only way we could actually implement the feature would be to silently generate exactly the code you've had to add yourself.
The small benefit afforded to developers of avoiding having to write those stub methods really does not justify the considerable cost of doing the more general covariance feature, so we've never done it.
It looks like you're assuming return type covariance, since ConcreteManager (as an IConcreteManager) expects both Create() and SelectAll() methods with a return type of IConcrete and IEnumerable<IConcrete> respectively, which the base class does not provide.
You are getting those errors because C# does not support return type covariance.
When you implement an interface/abstract class, you must use the same signature. See here
Don't let the generics throw you off, this is no different than if there were no generics.

Force generic interface implementation in C#

Is there anyway to force a constraints for a generic definition to implement a "generic interface" ... that is, I want the class to support passing an interface and a generic class constraining it so that the class implements the interface. For example if I say:
MyGenericClass<IMyInterface, MyImplementation>.DoSomething();
That should be constrained so that MyImplementation implements IMyInterface
As far as I know that can be achieved by
public class Dynamic_Loader<T, S> where S: T
Now, is there anyway to also force T to be an interface?
Edit: The purpose of this was to have something like:
private static List<T> interfaceList = new List<T>();
public static List<T> InterfaceList {get { return interfaceList;}}
public static void Add(S input) { interfaceList.Add(input);}
and have the list restricted to only interfaces (since it is supposed to return implementations of certain interfaces)
Do you mean, can a constraint also be put on T like where T : interface?
If so, then no: this list pretty much covers your options.
What you have is as close as it gets, I believe.
Out of curiosity, what would be your reason for wanting to constrain T to be an interface?
Or do you mean can a constraint also be put on T for T to implement some specific interface?
If so, then yes: simply have two where clauses (e.g., where S : T where T : U).
where T: IMyOtherInterfaceForT
Example:
public class Test<T, V>
where T : V
where V : IEnumerable<int>
{
}
You could do something like this to enforce it at runtime instead of compile time.
public class Test<T> where T : class
{
public Test()
{
Type t = typeof( T );
if( !t.IsInterface )
throw new ArgumentException( "T must be an interface type" );
}
}

Specify a C# Generic Constraint to be of ClassA OR ClassB?

Is there a way to specify that a generic type be of one type or another type?
public class SoftDrink<T>
where T : TypeOne or TypeTwo
{ }
Nope because that wouldn't make any sense. If you try to access a member function of "T", how can the compiler tell which base class to try and resolve members of?
You could try creating a common interface for TypeOne and TypeTwo and having the constraint specify that interface? What are you trying to accomplish, exactly?
You can't. The best you can do is use a common base class for the two, or a common interface implemented by both as a single type constraint.
No, however, you could constraint the class on a common base or interface.
In the CLR itself, the constraints (except for special ones, like the new-constraint) are stored rather simply: just a list of type identifiers, basically. So there's really no "room" for logical operations like you've specified... not without a revision to the CLR specification, or perhaps some really clever and ugly language-level tricks.
You can extract the common functionality of TypeOne and TypeTwo into a base class or interface, and use that base class or interface as the constraint. Otherwise, how would the compiler know what it could do with T?
public interface IBelch
{
void Belch();
}
public class Coke : IBelch
{
public void Belch()
{
}
}
public class GatorAde : IBelch
{
public void Belch()
{
}
}
public class SoftDrink<T>
where T : IBelch
{
public void DrinkFast(T drink)
{
drink.Belch();
}
}
You could always do a runtime check against the type:
class TypeOne
{
int _integer = 0;
}
class TypeTwo
{
int _integer = 3;
}
class TypeThree
{
}
class SoftDrink<T>
{
public SoftDrink()
{
if (typeof(T) != typeof(TypeOne) && typeof(T) != typeof(TypeTwo))
{
throw (new Exception("Sorry, but T must be TypeOne or TypeTwo"));
}
}
}
//this works:
SoftDrink<TypeOne> t1 = new SoftDrink<TypeThree>();
//throws an exception:
SoftDrink<TypeThree> t3 = new SoftDrink<TypeThree>();
You could have TypeOne and TypeTwo inherit an interface and then do the following.
public class SoftDrink<T>
where T: IMyType
{}

Categories

Resources