Generics and inheritance in C# - c#

I have entity class generated by E-R designer that I have modified a little. This is declaration:
public abstract partial class Preference<T> : EntityObject, IPreference<T>
Then there is another entity class declared as follows:
public partial class BoolPref : Preference<bool>
so BoolPref inherits from Preferences<bool>.
Now I have this generated property:
public ObjectSet<Preference<object>> Preferences
{
get
{
if ((_Preferences == null))
{
_Preferences = base.CreateObjectSet<Preference<object>>("Preferences");
}
return _Preferences;
}
}
private ObjectSet<Preference<object>> _Preferences;
When I try to add new BoolPref to this ObjectSet as follows
context.Preferences.AddObject(new BoolPref ());
I get compile time error.
How can I add instances of BoolPref to Preferences ? Where is the mystake ?

Suppose Preference<T> has a read-write property called Value of type T. Now suppose the type system works the way you'd like it to:
var set = new ObjectSet<Preference<object>>();
set.Add(new Preference<bool>());
set.First().Value = "hello";
That's legal at compile time because set.First().Value has compile time type of object, not bool. But at runtime it is of type bool, and you just called a setter that takes a bool and passed a string, corrupting memory in the CLR which then crashes and dies horribly.
That's why this is not legal. In C# 4 you can have generic covariance and contravariance only if it is provably typesafe, and only if the generic type is an interface or delegate, and only if the varying type argument is of reference type.

The short answer is that generics, out of the box, don't handle polymorphism in the same way which "normal" objects handle polymorphism-- Preference<object> and Preference<bool> are two mutually incompatible occasions of Preference<T> not a supertype/subtype.
The good news is that with .NET 4.0, you can use covariance to get the desired effect.
The other issue here is I'm not sure how the EF is going to be able to handle your class in terms of persistence as it probably has no idea what to do with Preference<T>.

The way around this is to have an IPreference interface that exposes the underlying value as an Object, so you can have an ObjectSet<IPreference>. The Preference<T> explicit implementation of IPreference would then need to check at runtime whether it is being provided values that match the underlying type.

Related

Conditional interface

For a project I'm on I'm unfortunately stuck with .NET 2.0 (many of our target machines are still Windows XP), which means no Optional type as Nuget's Optional library requires .NET 3.5.
Fortunately, rolling your own Optional type is pretty easy, but I've encountered one issue.
I would like something like the following:
class Optional<T> : (IComparable<Optional<T>> when T : IComparable<T>)
That is, I want my Optional type to implement Comparable, but only when the underlying type is Comparable.
The above syntax is sadly not valid, but is there a way achieve what I'm looking for?
Indeed this problem isn't confined to Optional, it will apply to any container type one wants to define that can implement it's internal type's interfaces.
I do realise I could do this:
class Optional<T>
class ComparableOptional<T> : Optional<T>, Comparable<ComparableOptional<T>>
where T : Comparable<T>
But this seems a bit silly, as then we really have to go down this rabbit hole:
class Optional<T>
class EquatableOptional<T> :
Optional<T>,
IEquatable<EquatableOptional<T>>
where T : IEquatable<T>
class ComparableOptional<T> :
EquatableOptional<T>,
IComparable<ComparableOptional<T>>,
IEquatable<ComparableOptional<T>>
where T : IComparable<T>
Furthermore, if T is Enumerable, Optional<T> can also be Enumerable (returning an empty enumerator if there is no value) so then we've got even more classes.
As Enumerable is orthogonal to Equatable and Comparable, we'd really need the following classes:
class Optional
class EquatableOptional
class ComparableOptional
class EnumerableOptional
class EnumerableEquatableOptional
class EnumerableComparableOptional
to cover all cases. Add another orthogonal interface and you've got 12 classes.
Is there a less messy approach that allows me to define interfaces conditionally? This seems like a common issue with any collection.
What you want to do infringes on the intention of how generics work in C#.
You're essentially arguing that type safety should be used as type possibility. Which is against the current C# ideology where you know a type's definition (and which methods and properties it exposes) for a fact.
The correct approach would be to have a second ComparableOptional<T> which derives from Optional<T> but adds an additional constraint:
class ComparableOptional<T> : Optional<T> where T : Comparable<T>
There is no benefit to your suggestion, other than the lazy approach of wanting to mash two different classes together. Even if the language would allow you to do so, I see no discernible benefit to this approach (compared to ComparableOptional<T>) but it does introduce a whole range of runtime errors that you can now encounter.
class Optional<T> : (IComparable<Optional<T>> when T : IComparable<T>) {}
Suppose everything works the way you expect it to.
var optionalPerson = new Optional<Person>() { Person = myPerson };
var optionalPerson2 = new Optional<Person>() { Person = myPerson2 };
int result = optionalPerson.CompareTo(optionalPerson2);
Should this work? In C# currently, it doesn't. But according to you, it should be able to if Person : IComparable<Person>. Your argument should be something like this:
Since the compiler sees me use the type Person : IComparable<Person>, it should be able to deduce that Optional<T> must now implement IComparable<T> and therefore the CompareTo() should be available.
The solidity of your argument rests solely on the fact that you know for a fact (at compile time) that the type you're using implements the needed interface.
But what about this code:
public void DoSomething<T>(Optional<T> opt1, Optional<T> opt2)
{
int result = opt1.CompareTo(opt2);
}
Should this work? You can't know, since you don't know which type will be used! Compounding the issue even further:
public void DoSomething(string optionalType, object opt1, object opt2)
{
var castObj = Convert.ChangeType(opt1, Type.GetType(optionalType)));
var castObj2 = Convert.ChangeType(opt2, Type.GetType(optionalType)));
int result = castObj .CompareTo(castObj2);
}
This method passes the used type as a string. So now you would expect the compiler to check the value of the string to figure out whether or not the generic type constraint of the type that is represented in the string implements a particular interface.
WHat if that string is retrieved from a database or external web service? Is the compiler now required to have an active database/web connection before it can decide whether your code is valid?
This is running out of hand.
Your likely counterarguments:
As long as I only use this method with types that implement IComparable<T>, the compiler should not throw an error. When I use a type that does not implement IComparable<T>, it should throw an error on the int result line.
That is not intuitive, and is going to lead to developer confusion.
The compiler should always assume that conditional generic type constraints are true.
So how would you handle mutually exclusive conditional generic type constraints, which logically will never both be true?
Welcome to the world of debugging hell. This is bad practice for the same reason that you shouldn't use dynamic over strongly typed approaches: it makes code considerably harder to maintain and develop.
Such an approach requires much more runtime testing to ensure that you haven't made a mistake somewhere that will blow up in your face. And runtime testing is a flawed approach.

The type T must be a reference type in order to use it as parameter while using interface

I got the error for the below code
public static Moq.Mock<T> CreateInstanceOfIMock<T>() {
return new Moq.Mock<T>();
}
I have solved the error it by using referred class type. See this below code
public static Moq.Mock<T> CreateInstanceOfIMock<T>() where T : class
{
return new Moq.Mock<T>();
}
Now I want to move this var mockColorsRepository = new Moq.Mock<IColorsRepository>(); code into common code by using generics. here IColorsRepository is an interface. So I made an interface reference for T instead of class like this below code
public static Moq.Mock<T> CreateInstanceOfIMock<T>() where T : interface
{
return new Moq.Mock<T>();
}
But am getting The type T must be a reference type in order to use it as parameter error. How can I refer interface instead of class to T. How can I achieve this?
class and struct in generic type constaints do not mean the same thing as the class and struct declarations that are used to declare class or struct types. Instead, they only restrict whether a generic type argument is a reference type (class), or a value type (struct).
So when you do where T : class you are not saying that T needs to be a class, you are saying that T needs to be a reference type. Similarly struct for value types.
Interfaces on their own do not have this property, so an interface can be implemented by both a reference type and a value type. As such, restricting your type to be of an interface does not really make sense there.
In your case, Moq requires you to pass a reference type, so you need to transitively carry over that type constraint in all your helper methods:
public static Moq.Mock<T> CreateInstanceOfIMock<T>()
where T : class
{
return new Moq.Mock<T>();
}
That’s all you need to do to create a mock of any valid type. You can use it with an interface using CreateInstanceOfIMock<IColorsRepository>() or any other type.
Of course, at that point, the method does not really make that much sense since it does not give you any benefit over just instantiating the mock yourself.
There's no generic constraint in C# to enforce that a type argument is an interface. But where T : class is really "where T is a reference type" - it includes interfaces.
If you wanted to enforce that T is an interface rather than a class, you could perform an execution-time check using typeof(T) within the method, but in this case it sounds like you don't really need to constrain it to be an interface.
I'm not sure that the "helper" method is particularly useful though - if you compare:
var mock = Helper.CreateInstanceOfIMock<Foo>();
and
var mock = new Moq.Mock<Foo>();
or even (unless you have Mock<T> as another type somewhere) just a using Moq; directive and
var mock = new Mock<T>();
The latter seems just as readable and shorter... it makes sense if you're going to add more logic in your method, but if it's only ever going to call the constructor, I don't think I'd bother with it.

List of generic objects with unknown type

I have the following two classes. The ConvertToType<T> class is an existing class and works fine, however when it is used an instance is created each time (via reflection), therefore I am creating a wrapper class to hold all the instances as they are created for efficiency.
public class TypeConverterHelper
{
private IList<ConvertToType<>> types;
}
internal class ConvertToType<T>
{
//snip
}
However, as you can see I need a list of my ConvertToType<T> class, but I can't specify the type as the whole point of these classes is that the type is unknown until runtime. I have researched this issue a fair amount, but without finding a successful solution. I know I could set the generic type to be an object, but there you could get un/boxing issues at some point. Adding an interface/abstract base class which is restricted to a struct looked like a good option, but unfortunately T could be a string, and possibly other custom classes at a later date so that solution doesn't work.
So does anyone have any other solutions/suggestions?
The list type has to be non-generic (since the generic type arguments cannot be predicted), so object would do, but it might be better to use a common non-generic base. Boxing/unboxing does not come into the discussion because ConvertToType is a reference type.
You would of course have to cast the values in the list back to ConvertToType<T> before being able to use them; the implementation could look like this:
public class TypeConverterHelper
{
private IList<object> types;
public ConvertToType<T> GetConverter<T>()
{
return types.OfType<ConvertToType<T>>.FirstOrDefault();
}
}

Is it possible to have non-generic method return generic type?

In Java I can easily write:
public interface MyInterface<T extends Object>
and then have a method which determine the T at runtime like:
public MyInterface<?> DetermineObjectAtRuntime()
But in C# where <?> is not available and I need to call the method with type; which means I need to know the type before hand.
Is it possible to return generics type from non-generic method?
If not, how can I work out the type to call such generic method if I have an object instance with that type?
For people who are not sure what this is for - I have a set of data structures which are using different enums as field indexers. All the messages extends from a common generic interface with that enum as type variable. Now I need to work out a method which deserialize all different types of messages from a byte[] array.
In C#, which does not have type erasure, there are several ways to work around not knowing a type argument at compile-time:
Non-generic subset: If it happens to be the case that the methods of MyInterface<T> that you need don't involve T, then you can extract that portion of the interface into a base interface and return the base interface instead.
Pro: No runtime type shenanigans.
Con: Modifies the type (moving methods to a new base interface), breaking binary compatibility.
Type checking wrapper: Make a RuntimeTypeCheckedMyInterface<T> class that implements MyInterface<object> by delegating to a MyInterface<T> after type checking. Have the method return a MyInterface<object>, created by wrapping the MyInterface<whatever> inside a RuntimeTypeCheckedMyInterface.
Pro: Works with any existing interface type, without modifying it.
Con: Introduces "does T=object really mean object, or does it mean unknown type"? ambiguity.
Manual type erasure: Make a variant of MyInterface<T> that doesn't have a T like MyInterfaceOfUnknownType. Make MyInterface<T> inherit from MyInterfaceOfUnknownType. Have your method return MyInterfaceOfUnknownType.
Pro: Acts basically identical to Java, with MyInterfaceOfUnknownType = MyInterface<?>.
Con: Pollutes MyInterface<T> with non-generic methods. When the methods differ only by return type you have to disambiguate with a name change. Modifies the type (breaking source and binary compatibility).
Screw the types: Have the method return object or dynamic. Cast conditionally and appropriately.
Pro: Initially easy to do.
Con: Harder to maintain.
"But in C# where '< ? >' is not available and I need to call the method with type; which means I need to know the type before hand."
You can use dynamic instead of <T> for example:
dynamic Foo (dynamic Input) {return Input;}
The compiler determines the type at runtime.
In C#, you can have generic methods:
class Foo<X>
{
public T DoSomethingFunky<T>( ... )
{
...
}
}
But there's no way to have a wildcard type — a big fail in C#. It would be very useful in a lot of situations where you that it is a Widget<T> but you don't care about the particulars of T.
For instance, WCF throws FaultException<T>, where the various flavors of T are service specific. There's no way to catch something like FaultException<*> without simply catching the base Exception class and using reflection to inspect the caught exception to see if it's an interesting T. This prevents handling service faults in a generic way.
I believe the reason is that a concrete generic class (Widget<int>) are not really subtypes of the generic class (Widget<T>) it "inherits" from. The generic class is simply used as a template to compile a new specific class.
The one thing you could do, is have your generic template (Widget<T>) inherit from a non-generic base class (Widget) and have your method return that:
class AbstractWidget { ... }
class Widget<T> : AbstractWidget { ... }
.
.
.
public Widget GetGeneric Widget()
{
/* flavor determinated at runtime */
}
It's incumbent upon the caller to decide what to do with its Widget.
Another way is to add an extension
public static class MyExtensions
{
public static T As<T>(this object obj)
{
return (T)obj;
}
}
the above will provide you a .As() method

Generic interfaces

Here is my code
public interface ITranslator<E, R>
{
E ToEntity<T>(R record);
}
class Gens : ITranslator<string, int>
{
#region ITranslator<string,int> Members
public string ToEntity<MyOtherClass>(int record)
{
return record.ToString();
}
#endregion
}
When I compile this, I get an error Type parameter declaration must be an identifier not a type
Why is that I cannot have ToEntity<MyOtherClass> but can only have ToEntity<T> ??
Edit: what is MyOtherClass doing ? I am converting between entities(POCOs equivalent of Entity framework) and record(Object returned by the framework) for multiple tables/classes. So I would want to use this to do my class specific conversion
Your interface has a generic ToEntity<T> method that you've made non-generic in your implementation class Gens as ToEntity<MyOtherClass>. (A generic method could take any type parameter, possibly given certain constraints on T. Your Gens class is trying to provide a definition for ToEntity only for the type parameter MyOtherClass, which defeats the purpose of generics.)
In your code example, it's unclear how your Gens class is trying to use the MyOtherClass type; it's certainly not involved in the logic of ToEntity. We'd need more information to be able to guide you further.
To illustrate, here's what your current definition of the ITranslator<E, R> interface offers, in plain English:
"I provide a mechanism to translate
any record of type R into an entity
of type E, this mechanism being
dependent upon any user-specified type
T."
Your Gens class, on the other hand, the way it's currently designed, "implements" the above interface like so:
"I can translate integers to strings.
I provide the illusion of allowing
the user to specify a type to control
how this translation is performed, but
in fact there is no choice of type.
The MyOtherClass class is involved
somehow; that's all I can say."
From these two descriptions, it's clear that the Gens class is not really doing what the ITranslator<E, R> interface guarantees. Namely, it is not willing to accept a user-specified type for its ToEntity method. That's why this code won't compile for you.
You must declare a constraint on a generic type.
public string ToEntity<T>(int record) where T : MyOtherClass
That compiles OK for me in LINQpad. Maybe you have a type named E, R, or T somewhere?
Ahh I see what you're trying to do... you have MyOtherClass defined as a class somewhere yet you're trying to use it as a type argument in ToEntity. How exactly do you want MyOtherClass involved in ToEntity?

Categories