问题
I did a little experiment on generics in C# and I had a problem where I want to pass a generic type as a type parameter with a constraint to implement a generic interface whose type I don't know.
Here is my example:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApplication3
{
class Program
{
interface IGenericCollection<T>
{
IEnumerable<T> Items { get; set; }
}
abstract class GenericCollection<T> : IGenericCollection<T>
{
public IEnumerable<T> Items { get; set; }
}
//This class holds a generic collection but i have to ensure this class
//implements my IGenericCollection interface. The problem here is that
//i dont know which type TGenericCollection is using and so i am unable to
//pass this information to the constraint.
class CollectionOwner<TGenericCollection>
where TGenericCollection : IGenericCollection< dont know ... >
{
protected TGenericCollection theCollection = default(TGenericCollection);
}
static void Main(string[] args)
{
}
}
}
I have read several posts here, and all told me its impossible due to limitations of C# and CLR. But what would be the right way to do this?
回答1:
Perhaps you should another type parameter:
class CollectionOwner<TGenericCollection, T2>
where TGenericCollection : IGenericCollection<T2>
where T2 : class
{
protected TGenericCollection theCollection = default(TGenericCollection);
}
Will this suit you need?
回答2:
I don't think there's a problem here, just add another generic parameter to your Owner class:
class CollectionOwner<T,TGenericCollection>
where TGenericCollection : IGenericCollection<T>
{
protected TGenericCollection theCollection = default(TGenericCollection);
}
回答3:
You can add the second generic parameter to the implementation class. The static Example
method below shows an example of this.
public interface ITest<T>
{
T GetValue();
}
public class Test<T, U> where T : ITest<U>
{
public U GetValue(T input)
{
return input.GetValue();
}
}
public class Impl : ITest<string>
{
public string GetValue()
{
return "yay!";
}
public static void Example()
{
Test<Impl, string> val = new Test<Impl,string>();
string result = val.GetValue(new Impl());
}
}
回答4:
Using a second generic parameter is an option 4 sure which i already wanted to use but what about this
abstract class GenericCollection<T> : IGenericCollection<T>
{
public IEnumerable<T> Items { get; set; }
}
class ConcreteCollection : GenericCollection<string>
{
}
static void Main(string[] args)
{
// will constraint fail here ?
CollectionOwner<int,ConcreteCollection> o = new CollectionOwner(int, ConcreteCollection);
}
来源:https://stackoverflow.com/questions/15301197/passing-a-generic-as-generic-type-parameter-in-c-sharp