Extract Generic Type From Enclosing Generic - c#

I want something like this:
class Foo<T>{...}
class Boo<T>{
Queue<T> stuff = new Queue<T>();
public void Boo(Foo<T>){...};
}
...
//Extract the generic type - string - to define the type
//of MyBoo.
var MyBoo = new Boo(new Foo<string>());
I get the error "generic type 'Boo' requires '1' type arguments. Ya, I fixed the problem by stating the template type explicitly, but I'd like to know if there was/is a way to extract that type implicitly, rather than having to state it explicitly.
This other post may be related, but I'm not sure.

You can't do it implicitly directly with the constructor of a generic type, but you could from a generic method, e.g. in a non-generic class:
public static class Boo
{
public Boo<T> Create<T>(Foo<T> foo)
{
return new Boo<T>(foo);
}
}
Then:
// myBoo will be inferred to be of type Boo<string>
var myBoo = Boo.Create(new Foo<string>());
Of course, it doesn't have to be another class called Boo - it could be something completely different, and it could be an instance method of something else:
var factory = new BooFactory();
var myBoo = factory.Create(new Foo<string>());
The important point is that it's a generic method - type arguments can be inferred for generic methods, but not for generic types.

Type inference works only with methods. So if you have generic method and it is clear how to substitute generic parameter it will be substituted by compiler. For new operator it doesn't work so consider creating factory method like Create that will produce instances of Boo. Otherwise impossible.

Related

Cannot convert type 'T' to 'T'?

I renamed the question from: "Why does my UpCast() not compile as an instance method but does as an extension?" to something a bit more useful for the future emaciated adventurer.
I originally set out to implement an UpCast() as an instance method, but eventually ended up boggling over a compiler message that didn't seem to make sense. The original question is below, with the update.
I have a container class derived from ObservableCollection. Just now I tried to write an UpCast<> generic method so that instead of writing:
Columns = new MegaList<DbTableColumn>();
Columns.AddRange( oracleDictionary.ListTableColumns(tableName) ); // IEnumerable<OracleColumn>
// or
(v.Columns = new MegaList<DbTableColumn>()).AddRange( oracleDictionary.ListTableColumns(tableName) );
// I could instead write
Columns = oracleDictionary.ListTableColumns(tableName).UpCast<DbTableColumn>();
MegaList is ObservableCollection with some added convenience methods that I won't show here. Since ObservableCollection does not have ConvertAll(), I tried this.
Basically, why doesn't the following instance method compile, yet I can implement the seemingly equivalent as an extension method (listed at the bottom), it does?
public class MegaList<T> : ObservableCollection<T>
{
// ...rest of class snipped...
public ObservableCollection<TBase> UpCast<TBase, T>()
where TBase: class
where T : TBase
{
var listUpcast = new ObservableCollection<TBase>();
foreach (T t in this.Items) <-- Error 14 Cannot convert type 'T' to 'T' ??? Excuse me?
listUpcast.Add(t);
return listUpcast;
}
}
I think the following is equivalent. Just exchanges the "this" parameter for the OberservableCollection.Items property, both hold type T. I am especially confused because of the type constraint that states "T must be TBase".
static public ObservableCollection<TBase> UpCast<TBase, T>(this ObservableCollection<T> list)
where TBase : class
where T : TBase
{
var listUpcast = new ObservableCollection<TBase>();
foreach (var t in list)
listUpcast.Add(t);
return listUpcast;
}
UPDATE:
The answer is below, and I found the following to be true:
C# has generic type parameter shadowing, just like regular
field/parameter shadowing.
I can't write a type constraint in a
generic method using a type parameter from the enclosing class,
because of (1) and I don't think there is a way to refer to type within a type constraint, where T is a generic type parameter.
I don't like to answer my own question, but this one had me stumped and visually it doesn't make sense, and nobody else explained it.
After a night's sleep, it dawned on me that this is simply generic parameter shadowing. Shadowing of generic parameters apparently exists (I did not know this since I don't write inner classes much), and works just like standard parameters. So even though T is a type parameter in the outer class, the compiler treats the T in the inner method (or class) as T2, and they are not the same type, hence the error which amounts to "T is not assignable to T" because I am trying to iterate an IList with T (which should work if you look at it purely from a symbolic level). The error is:
public class MegaList<T> : ObservableCollection<T>
{
public ObservableCollection<TBase> UpCast<TBase, T>() // <-- this T isn't outer T
where TBase : class
where T : TBase
{
var listUpcast = new ObservableCollection<TBase>();
foreach (T t in this.Items) // <-- error: Argument type 'T' is not assignable to parameter type 'TBase'
listUpcast.Add(t);
return listUpcast;
}
}
And since I'd have to provide T as a generic parameter, I cannot constrain it on the inner method, which #hvd supports, so unless someone knows some syntax that I don't, I'll just give up on this and either use a cast within the method, or stick with the extension method where I can type constrain it.
I honestly cannot decide if this is a feature, or a limitation. I guess it would depend on your point of view. Hope this helps someone else. At least the C# compiler should probably improve the error message so that there is an apparent difference between types. Given that one is declared in an outer scope (so to speak) I don't see why the types should be listed as Foo.T vs Foo.T, I would think the inner T would be in the symbol namespace of the outer class, and hence have a different qualified type name like MegaList.T vs MegaList.UpCast.T.
Should not the definition of UpCast method be
public class MegaList<T> : ObservableCollection<T>
{
// ...rest of class snipped...
public ObservableCollection<TBase> UpCast<TBase>()
{
var listUpcast = new ObservableCollection<TBase>();
foreach (var t in this.Items)
listUpcast.Add((TBase)t); // <-- error: Argument type 'T' is not assignable to parameter type 'TBase'
return listUpcast;
}
}

How to specify the type of an anonymous type while using a generic type

The title is pretty confusing. I will try to explain with an example. Consider the code below:
String[] str={"Apple","Banana","Cherry","Orange"};
var anoCollection=from e in str select new
{
ch=e[0],
length=e.Length
}
dataGridView.DataSource=anoCollection.ToList(); //TypeInitializationException
I feel that I need to mention the type in above case for the ToList<T>() method. But how can I mention an anonymous type here?
It is never possible to mention an anonymous type directly, but you should not need to. Generic type inference means that you don't need to specify the <T> in .ToList<T>() - the compiler will automatically inject the invented type.
There are only a few ways to refer to an anonymous type:
via someObj.GetType(), where someObj is an instance of an anonymous type
via generics, as a T, by calling a generic method via generic type inference (as in ToList())
various other usages of reflection, pulling in the T via GetGenericTypeParameters()
This may be not what you are asking for, but if you later want to use the DataBoundItem for a row, you can do it this way:
var item = TypeExtensions.CastByPrototype(row.DataBoundItem, new { ch = 'a', length = 0});
//you can use item.ch and item.length here
Trace.WriteLine(item.ch);
with the support of this method:
public static class TypeExtensions
{
public static T CastByPrototype<T>(object obj, T prototype)
{
return (T)obj;
}
}

Is there an (elegant) solution to constrain a generic type argument further within a method?

I have a generic base class Foo<T> from which the classes Bar<U> and Bat<T> derive.
U derives from T. Bat and Bar are similar implementations that differ only in a few places where values of type U must be handled in a different manner.
In Foo, I have a factory method Create that takes an argument of type T and should create either a Bar or Bat object.
It looks roughly like this:
public static IFoo<T> Create(T input) {
if (input.TypeIdentifier == Types.Bar) {// exemplary type check
// input is of or derives from `U`
// return a Bar<U>
} else
return new Bat(input);
}
// usage:
U myU = new ClassThatDerivesFromU();
T myT = new ClassThatDerivesFromT(CouldBe.Of(Type.U));
var myFoo1 = Create(myU); // of type IFoo<U>
var myFoo2 = Create(myT); // of type IFoo<T>
Since T is not a U, I cannot instantiate a Bar object.
One possible solution would be this:
public static U To<T, U>(T input) where U : T {
return input as U;
}
// to create Bar:
new Bar(To<T, U>(input));
However this is quite the hack imo and would not be usable with structs (U in this case cannot be a struct anyway due to inheritance, but I have another case where I want to call methods depending on if T is a struct or a class for example).
In C++ a scenario like this can be solved (iirc) by providing several overloads of the Create method with different type constraints and the compiler will check the type T and pick the right method (with either U or T as type constraint).
I'm not aware of a similar built-in solution in C#, but perhaps there is an elegant workaround I can use instead? (Reflection is an obvious answer, but not an option)
Yes, generic variance is allowed when using interfaces. You can declare the generic type parameter within IFoo to be either covariant or contravariant (depending upon the usage). If you wish to use a more derived type, then the type T must be contravariant and IFoo can be declared as follows:
interface IFoo<in T> { ... }
Have a look at this MSDN page for more information on generics and variance in C#.
Update
Once you have the condition that an IFoo<U> is IFoo<T> if U : T (eg the generic type of IFoo is contravariant) then you are free to safely cast within your create method:
return (IFoo<T>)((object)new Bar<U>());

In C#, is it possible to determine the type parameter of a generic at runtime?

Here's sort of what I have (using Rhino Mocks, but that isn't central to the question):
var entityMock = MockRepository.GenerateMock<IEntity>();
this.Cache = MockRepository.GenerateStub<Cache<IEntity>>();
Is it possible to be more specific in setting the type parameter of Cache<T>? Something like:
var entityMock = MockRepository.GenerateMock<IEntity>();
this.Cache = MockRepository.GenerateStub<Cache<typeof(entityMock)>>();
This doesn't compile of course. But I would like to, if possible, use the type that Rhino Mocks generates, which is a concrete implementation of IEntity.
You can create a closed generic type at runtime using reflection. The problem is that you will most likely have to continue operating it using just reflection because (given that its type is not known at compile time) you cannot type it as something usable directly.
For example, to create a list of "something":
public IList CreateList(Type t)
{
var openListType = typeof(List<>);
return (IList)openListType.MakeGenericType(t);
}
This example illustrates a couple of important points:
You cannot do this if the "target type" is specified at compilation. In other words, CreateList cannot accept t as a generic type parameter and still allow the same functionality.
In the worst case scenario the new instance cannot be typed as anything else than object. Here we know that we will always create an IList, so things are a bit better.
I don't have experience with Rhino Mocks, but in your case it would translate to this:
var entityMock = MockRepository.GenerateMock<IEntity>()
var cacheType = typeof(Cache<>).MakeGenericType(entityMock.GetType());
this.Cache = MockRepository.GenerateStub(cacheType);
...but only if an appropriate GenerateStub overload is available.
Note that although RhinoMocks is mentioned, the only specific part is GenerateStub which creates a concrete implementation around the provided type; the rest is agnostic of RhinoMocks.
Generic type arguments are resolved at compile time - as you know; this disallows entering the type as a generic argument in-line without reflection (ie: var list = new List<typeof(int)>();).
However, you can create generic types using reflection. In essense, if you can get the type of the dynamic proxy from something like:
var entityMock = MockRepository.GenerateMock<IEntity>();
var dynamicType = entityMock.GetType();
MockRepository has a GenerateStub that takes a Type and object[] arguments, so carrying on from above:
var cacheType = typeof(Cache<>);
var genericType = cacheType.MakeGenericType(dynamicType);
var stubbed = MockRepository.GenerateStub(genericType, null);
The stubbed item is unfortunately of type object, but as Lucero states in the comments, it would be possible to use generic co-variance to gain a type more usable than just object. I demonstrate this below.
Based on an interesting discussion with Lucero, if you define a new ICache<out T> interface to represent the Cache, the generic co-variance will then allow you to cast the resulting proxies to the base type (of ICache<IEntity>):
class Program
{
static void Main(string[] args)
{
// The concrete entity.
IEntity entityMock = MockRepository.GenerateMock<IEntity>();
entityMock.Stub(s => s.Name).Return("Adam");
// The runtime type of the entity, this'll be typeof(a RhinoMocks proxy).
Type dynamicType = entityMock.GetType();
// Our open generic type.
Type cacheType = typeof(ICache<>);
// Get the generic type of ICache<DynamicProxyForIEntity> (our closed generic type).
Type genericType = cacheType.MakeGenericType(dynamicType);
// Concrete instance of ICache<DynamicProxyForIEntity>.
object stubbed = MockRepository.GenerateStub(genericType, null);
// Because of the generic co-variance in ICache<out T>, we can cast our
// dynamic concrete implementation down to a base representation
// (hint: try removing <out T> for <T> and it will compile, but not run).
ICache<IEntity> typedStub = (ICache<IEntity>)stubbed;
// Stub our interface with our concrete entity.
typedStub.Stub(s => s.Item).Return(entityMock);
Console.WriteLine(typedStub.Item.Name); // Prints "Adam".
Console.ReadLine();
}
}
public interface ICache<out T>
{
T Item { get; }
}
public interface IEntity
{
string Name { get; }
}
If code will wish to perform different actions based whether or not a generic type meets certain constraints, especially if some of these actions can't even compile if the generic type doesn't, it may be helpful to use a pattern somewhat similar to the that used by classes like Comparer<T> and EqualityComparer<T>. The trick is to use a static class with a generic parameter T which holds a static delegate to a method which has a parameter of type T, and have static methods, each of which takes a possibly-constrained generic parameter of type U and has a signature that will be compatible with the aforementioned delegate when U matches T. The first time an attempt is made to use the static class or its delegate, the static constructor of the generic class can use Reflection to construct a delegate to the method which should be used for the type. Such a call will fail at run-time if one attempts to construct a delegate to a generic method in such fashion as to violate the generic constraints of thereof; since exceptioins in static constructors are very bad, one should make sure to construct one's delegates using valid functions. On the other hand, once the delegate has been constructed once, all future calls can be dispatched straight through that delegate, with no need for further Reflection or type checking.

What are the advantages of using generics in method signatures?

(Thanks everyone for the answers, here is my refactored example, in turn another StackOverflow question about the Single Responsibility Principle.)
Coming from PHP to C#, this syntax was intimidating:
container.RegisterType<Customer>("customer1");
until I realized it expresses the same thing as:
container.RegisterType(typeof(Customer), "customer1");
as I demonstrate in the code below.
So is there some reason why generics is used here (e.g. throughout Unity and most C# IoC containers) other than it just being a cleaner syntax, i.e. you don't need the typeof() when sending the type?
using System;
namespace TestGenericParameter
{
class Program
{
static void Main(string[] args)
{
Container container = new Container();
container.RegisterType<Customer>("test");
container.RegisterType(typeof(Customer), "test");
Console.ReadLine();
}
}
public class Container
{
public void RegisterType<T>(string dummy)
{
Console.WriteLine("Type={0}, dummy={1}, name of class={2}", typeof(T), dummy, typeof(T).Name);
}
public void RegisterType(Type T, string dummy)
{
Console.WriteLine("Type={0}, dummy={1}, name of class={2}", T, dummy, T.Name);
}
}
public class Customer {}
}
//OUTPUT:
//Type=TestGenericParameter.Customer, dummy=test, name of class=Customer
//Type=TestGenericParameter.Customer, dummy=test, name of class=Customer
One reason when generics are very useful is when the generic type parameter is used as the type of a parameter or as the return type of the method.
That means, you can write methods like
public T GetAs<T>(string name)
where the return type can be checked by the compiler and boxing value types can sometimes be avoided.
The caller would write:
int value = GetAs<int>("foo");
Whithout generics, you would have to write
public object GetAs(Type t, string name)
and the caller has to cast the result again:
int value = (int)GetAs(typeof(int), "foo");
A primary reason is the type safety at compile time. If you are passing two Type objects you are placing the responsibility at the developer instead of the compiler.
This is also why many IoC containers utilizes it, as your compiler will complain if an concrete type isn't inheriting the abstract type.
public void Register<TAbstract, TConcrete>() where TConcrete : TAbstract
{
}
This code will only work if TConcrete is implementing or inheriting TAbstract. If this method took two Type parameters, your method should validate this relationship.
A simple answer is type inference where possible.
If the generic type is used in the method signature, you can omit it because the type could be inferred:
void SomeMethod<T>(T x, T y) where T : IComparable<T> {
Console.WriteLine("Result: {0} to {1} is {2}", x, y, x.CompareTo(y));
}
So the usage is simplified:
SomeMethod(3, 4); // instead of SomeMethod<int>(3, 4);
SomeMethod("one", "two"); // instead of SomeMethod<string>("one", "two");
If the generic type parameter is not used in the method signature the type inference is not possible:
var emptySequence = Enumerable.Empty<int>();
I think one of the primary uses is type safety with arguments and return values. In your example case, there is not much use for generics, because the input/output types (string) do not match the generic case (customers).
A more appropriate use might be:
public T RegisterType<T>(string name)
{
T obj = new T();
obj.DoSomething();
return obj;
}
or maybe
public void DoSomething<T>(T obj)
{
//operate on obj
}
If you didn't use Generics, you'd either have to overload a method for each type you want to support, or you'd have to accept the parameter as an object and perform casting logic.
For one example, compare the code needed to create an instance of your type using the typeof option versus a generic. Or return an instance of the type. Or accept an instance of the type as an argument. Or set a property on an instance of the type.
In general, if you will be working only with the type itself you can accept a type parameter. If you want to do anything with an instance of the type, use a generic.
Another reason to use a generic is if you want to apply constraints to the type. For example, you can require the type to implement one or several interfaces, inherit another type, be a reference type or value type, have a default constructor, or some combination of the above. The compiler will enforce this so you can't build code that doesn't comply with your requirements.
I'd say the best reason is type safety, using the "where" keyword, to ensure that the generic type is of a certain type (or sub-class/implementor). Using "typeof" will let you send anything through.

Categories

Resources