Reputation: 4339
Is something like this possible?
Dim l As New List(Of T As Type Where GetType(BaseClass).IsAssignableFrom(T))
Note, my collection will be a collection of Types, not objects of type T - which I know is possible.
ETA:
The answers I've had so far are as expected - I didn't think it was possible.
What I'm trying to get my head round is why the following can resolved at compile time, but not my example:
Dim l as New List(Of T As BassClass)
Are the checks not, essentially, the same?
Upvotes: 0
Views: 123
Reputation: 81247
It's possible to achieve a collection of things which abide by multiple generic constraints without using Reflection, but it's pretty icky. Each item added to the collection will have to be wrapped with a class object. If the collection is supposed to hold things constrained to I1
and I2
, each item will be wrapped in an instance of a generic class with types T
, I1
, and I2
(constrained so T:I1,I2
), which implements an interface with generic types I1
and I2
. The collection itself will hold references of that interface type.
If anyone is interested, I could post more details.
Upvotes: 0
Reputation: 21609
To do it you'll need to create Type(Of TBase) class, then make a list of them. Then you can try to guarantee that Type(Of TBase) is statically correct.
But in most cases, where you need to create Type(Of TBase) from CLR Type, it can be guaranteed only dynamically.
Upvotes: 0
Reputation: 99979
You can have a runtime enforced constraint on your collection like this:
public class ConstrainedTypeCollection<TBaseType> : Collection<Type>
{
protected override void InsertItem(int index, Type item)
{
if (!typeof(TBaseType).IsAssignableFrom(item))
throw new ArgumentException("The type is incompatible.", "item");
base.InsertItem(index, item);
}
protected override void SetItem(int index, Type item)
{
if (!typeof(TBaseType).IsAssignableFrom(item))
throw new ArgumentException("The type is incompatible.", "item");
base.SetItem(index, item);
}
}
Edit: You could also do the following and get full compile-time type safety as long as you call the generic Add<T>()
, Contains<T>()
, and Remove<T>()
methods.
public class ConstrainedTypeCollection<TBaseType> : ICollection<Type>
{
private readonly List<Type> _collection = new List<Type>();
public void Add<T>()
where T : TBaseType
{
_collection.Add(typeof(T));
}
public bool Contains<T>()
where T : TBaseType
{
return _collection.Contains(typeof(T));
}
public bool Remove<T>()
where T : TBaseType
{
return _collection.Remove(typeof(T));
}
public int Count
{
get
{
return _collection.Count;
}
}
bool ICollection<Type>.IsReadOnly
{
get
{
return false;
}
}
public void Clear()
{
_collection.Clear();
}
public void CopyTo(Type[] array, int arrayIndex)
{
_collection.CopyTo(array, arrayIndex);
}
public IEnumerator<Type> GetEnumerator()
{
return _collection.GetEnumerator();
}
#region ICollection<Type> Members
void ICollection<Type>.Add(Type item)
{
VerifyType(item);
_collection.Add(item);
}
bool ICollection<Type>.Contains(Type item)
{
VerifyType(item);
return _collection.Contains(item);
}
bool ICollection<Type>.Remove(Type item)
{
VerifyType(item);
return _collection.Remove(item);
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
private void VerifyType(Type item)
{
if (!typeof(TBaseType).IsAssignableFrom(item))
throw new ArgumentException("The type is incompatible.", "item");
}
}
Upvotes: 2
Reputation: 239764
The checks aren't the same - in your first example, you're asking the compiler to call the "IsAssignableFrom" method, and then do something based on the result. In the second example, you're asking the compiler's static type checker to do some work.
In general, the compiler doesn't call arbitrary code during compilation.
And also, remember that any type constraints on generics have to be embedded in your assemblies metadata. And again, you can't put arbitrary code in a generic type constraint.
Upvotes: 2
Reputation: 7399
I don't think it's possible to have that checked statically at compile time. But you could override Add, AddRange, and this[] to check added elements at run-time.
Upvotes: 0
Reputation: 3350
No it cannot be. The Type in generic need to be resolve at compile time.
Upvotes: 0