I have a piece of code that attempts to cast and return an object called m_obj
depending on a given generic type. Here is the code:
private IObject m_obj;
public bool TryGetAs<T>(out T value) where T :IObject
{
value = m_obj as T; // The type parameter 'T' cannot be used with the 'as' operator because it does not have a class type constraint nor a 'class' constraint
// value = (T)m_obj; This compiles!
if (value != null)
return true;
return false;
}
I know that if m_obj
were a list, I could do this:
private readonly IList<Object> m_objects;
internal IList<T> Collect<T>() where T : IObject
{
return m_objects.OfType<T>().ToList();
}
However, I cannot figure out how to solve the problem in the first code example. Here is the original code again:
public interface IObject
{
}
This is my proposed solution:
public bool TryGetAs<T>(out T value) where T :IObject
{
value = default(T);
if (!(m_obj is T))
return false;
value = (T)m_obj;
return true;
}
I would like to know if my solution is correct and if there are any better or more elegant ways to solve this problem.
The as
operator is reserved for reference types. If T
is always a reference type, the solution is to add a class
constraint to TryGetAs<T>
. If T
can also be a value type, this is not an option. In this case you can use the is
operator:
public bool TryGetAs<T>(out T value) where T : IObject
{
if(m_obj is T)
{
value = (T)m_obj;
return true;
}
else
{
value = default(T);
return false;
}
}
In C# 7.0 you can simplify it like this (and improve performance since you don't need an is
cast and then another type cast):
public bool TryGetAs<T>(out T value) where T : IObject
{
if(m_obj is T tValue)
{
value = tValue;
return true;
}
else
{
value = default(T);
return false;
}
}