Derived interface from generic method
I'm trying to do this:
public interface IVirtualInterface{ }
public interface IFabricationInfo : IVirtualInterface
{
int Type { get; set; }
int Requirement { get; set; }
}
public interface ICoatingInfo : IVirtualInterface
{
int Type { get; set; }
int Requirement { get; set; }
}
public class FabInfo : IFabricationInfo
{
public int Requirement
{
get { return 1; }
set { }
}
public int Type
{
get {return 1;}
set{}
}
}
public class CoatInfo : ICoatingInfo
{
public int Type
{
get { return 1; }
set { }
}
public int Requirement
{
get { return 1; }
set { }
}
}
public class BusinessObj
{
public T VirtualInterface<T>() where T : IVirtualInterface
{
Type targetInterface = typeof(T);
if (targetInterface.IsAssignableFrom(typeof(IFabricationInfo)))
{
var oFI = new FabInfo();
return (T)oFI;
}
if (targetInterface.IsAssignableFrom(typeof(ICoatingInfo)))
{
var oCI = new CoatInfo();
return (T)oCI;
}
return default(T);
}
}
But getting a compiler error: Canot convert type 'GenericIntf.FabInfo' to T
How do I fix this?
thanks Su开发者_StackOverflow中文版nit
Assuming all IVirtualInterface implementations will have a default constructor (as in your example), you can do this instead:
public T VirtualInterface<T>() where T : IVirtualInterface, new()
{
return new T();
}
Simples!
EDIT:
Exactly what you're trying to achieve is difficult to determine from the code you've posted. Why isn't VirtualInterface static (implies all business objects inherit this method which seems odd)? If you need o be able to parameterised constructors for your IVirtualInterface implementations, where would those parameter values come from (you're not passing any into the VirtualInterface method)?
If you just want to avoid cluttering up intellisense (a poor reason for trying something like this IMHO) but also want to maintain support for parameteried constructors, then how about this:
public T VirtualInterface<T>(Func<T> constructor) where T : IVirtualInterface
{
return constructor();
}
With usage:
IFabricationInfo fabInfo =
new BusinessObj().VirtualInterface<IFabricationInfo>(() => new FabInfo());
Overall though, and without enough information to make a solid judgement, I'd have to say that this smells.
The fact that T
and FabInfo
both implement IVirtualInterface
does not mean you can perform a cast between the two types. For example if T
is CoatInfo
, then it is not compatible type with FabInfo
.
Interfaces allow you to treat different objects as similar types based on the methods they provide. However, this does not mean that you can perform casts between these two types as their actual implementation can vary greatly.
Edit: After re-reading your method again, I see that you are checking the type first. The problem is that the compiler doesn't know you are performing that logic before you try to make that cast. If you are writing a generic method and are checking the type of T
, you are likely misusing the concept of generics. See the other answers for the way you should be creating new instances of T
.
You can get around this error by first casting to object
before casting to T e.g.
return (T)(object)oFI;
and similarly for CoatInfo
However I think switching on a generic type is an abuse, since if you want a limited number of possible return values, you could make the options explicit e.g.
public IFabricationInfo GetFabricationInfo()
{
return new FabInfo();
}
精彩评论