This question already has answers here:
Closed 7 years ago.
If I have a generic Item class that looks like this:
abstract class Item<T>
{
}
And a Container of Items that looks like this:
class Container<TItem, T>
where TItem : Item<T>
{
}
Since TItem depends on T, is it possible to simplify the type signature of Container so that it takes only one type parameter? What I really want is something this:
class Container<TItem>
where TItem : Item // this doesn't actually work, because Item takes a type parameter
{
}
So I can instantiate it as follows:
class StringItem : Item<string>
{
}
var good = new Container<StringItem>();
var bad = new Container<StringItem, string>();
The compiler should be able to deduce that T is string when TItem is StringItem, right? How do I make this happen?
Desired usage:
class MyItem : Item<string>
{
}
Container<MyItem> container = GetContainer();
MyItem item = container.GetItem(0);
item.MyMethod();
This should do what you want I think. Obviously you're now doing Container<string>
not Container<StringItem>
but as you've not included usage examples I can't see it being a problem.
using System.Collections.Generic;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
var myContainer = new Container<string>();
myContainer.MyItems = new List<Item<string>>();
}
}
public class Item<T> { }
public class Container<T>
{
// Just some property on your container to show you can use Item<T>
public List<Item<T>> MyItems { get; set; }
}
}
How about this revised version:
using System.Collections.Generic;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
var myContainer = new Container<StringItem>();
myContainer.StronglyTypedItem = new StringItem();
}
}
public class Item<T> { }
public class StringItem : Item<string> { }
// Probably a way to hide this, but can't figure it out now
// (needs to be public because it's a base type)
// Probably involves making a container (or 3rd class??)
// wrap a private container, not inherit it
public class PrivateContainer<TItem, T> where TItem : Item<T> { }
// Public interface
public class Container<T> : PrivateContainer<Item<T>, T>
{
// Just some property on your container to show you can use Item<T>
public T StronglyTypedItem { get; set; }
}
}
I think one possible solution to your problem is adding interface IItem
and the code structure will be like following.
interface IItem { }
abstract class Item<T> : IItem { }
class Container<TItem> where TItem : IItem { }
class StringItem: Item<string> { }
And now you can have the Container<StringItem>
:
var container = new Container<StringItem>();