why do I get a compiler error in the following code stating: Cannot implicty convert type SpecialNode to T even though T must derive from NodeBase as I defined in the where clause and even though SpecialNode actually derived from NodeBase?
public static T GetNode<T>() where T : NodeBase
{
if (typeof(T) == typeof(SpecialNode))
{
return ThisStaticClass.MySpecialNode; // <-- compiler error
}
if (typeof(T) == typeof(OtherSpecialNode))
{
return ThisStaticClass.MyOtherSpecialNode; // <-- compiler error
}
...
return default(T);
}
The compiler doesn't read your if check to realize that in this particular line, T must be SpecialNode.
You need to cast to NodeBase first, like this:
return (T)(NodeBase)MySpecialNode;
You need to casts because (as far as the compiler knows) T might be MyOtherSpecialNode, and you cannot cast a MyOtherSpecialNode to MySpecialNode.
EDIT: You can do it with a single cast like this:
NodeBase retVal;
if (typeof(T) == typeof(SpecialNode))
retVal = MySpecialNode;
else if (typeof(T) == typeof(OtherSpecialNode))
retVal = MyOtherSpecialNode;
return (T)retVal;
You might see that a condition has been logically met, but the compiler does not "remember" this.
public static T GetNode<T>() where T : NodeBase
{
if (typeof(T) == typeof(SpecialNode)) // OK, you now know T is SpecialNode
{
// the compiler still insists on returning a T,
// and will not assume that MySpecialNode is a T
return MySpecialNode;
}
// ...
return default(T);
}
It's true what others have already said: you must cast MySpecialNode: (T)(NodeBase)MySpecialNode (which you can do safely, because you have already checked that T is SpecialNode).
It's easy to think of this as a shortcoming of the compiler; but this is just a mistake stemming from how obvious it seems that MySpecialNode is a T. Suppose I had a method like this:
public T Get<T>() {
if (typeof(T).FullName.Equals("System.Int32"))
return 5;
else
return default(T);
}
Should this compile? I should hope not; the compiler needs to guarantee that it's returning an object of type T, and it can't be sure that 5 will meet that requirement just from some bizarre check that I the developer have performed. (Yes, I know that T is int, but I would not expect any reasonable compiler to determine that from a comparison of the System.Type.FullName property.)
Checking if (typeof(T) == typeof(SpecialNode)) is really not so different from that.
The problem is that the function may be called with a type parameter T, which derives from NodeBase but not from SpecialNode. The compiler doesn't check the semantics of the if statement, so it doesn't know, that T has to be a specialNode.
You would need to use an explicit cast to T in order to satisfy your compiler.
You could also do:
public static T GetNode<T>() where T : NodeBase
{
T result;
result = ThisStaticClass.MySpecialNode as T;
if (result != null) return result;
result = ThisStaticClass.MyOtherSpecialNode as T;
if (result != null) return result;
return default(T);
}
Edit: If the static classes are already null, this probably wouldn't have the intended effect.
Ah, that moment you wish the language had some kinda static polymorphism. Type checking in a generic method is not very cool. This can be a better solution if your requirements let:
public abstract class NodeBase
{
public abstract NodeBase GetNode();
}
public class SpecialNode : NodeBase
{
public override NodeBase GetNode()
{
return ThisStaticClass.MySpecialNode;
}
}
public class OtherSpecialNode : NodeBase
{
public override NodeBase GetNode()
{
return ThisStaticClass.MyOtherSpecialNode;
}
}
//and in your generic method, just:
public static T GetNode<T>() where T : NodeBase, new()
{
return (T)new T().GetNode();
}
This suffer from a disadvantage that you have to expose a parameterless constructor. In case that's undesirable, may be a slightly better approach is to push the generic call one layer backward, and ask your static class itself to do the work for you. Changing static class definition to something like:
public static T GetNode<T>() where T : NodeBase
{
return ThisStaticClass<T>.GetNode();
}
//in which case ThisStaticClass<T> have awareness of
//parameterless new() constructor of T class, which still need not be good enough
You can get it a bit more strongly typed by going one generic level deeper.
public abstract class NodeBase<T> where T : NodeBase<T>
{
public abstract T GetNode();
}
public class SpecialNode : NodeBase<SpecialNode>
{
public override SpecialNode GetNode()
{
return ThisStaticClass.MySpecialNode;
}
}
public class OtherSpecialNode : NodeBase<OtherSpecialNode>
{
public override OtherSpecialNode GetNode()
{
return ThisStaticClass.MyOtherSpecialNode;
}
}
//avoids cast
public static T GetNode<T>() where T : NodeBase<T>, new()
{
return new T().GetNode();
}
Why not just do the following:
return (T)MySpecialNode;
What version of .NET?
See my answer from a previous post
Using Generics to return a literal string or from Dictionary<string, object>
but the answer is
return (T)MySpecialNode
Because even you do the if check the compiler does not so you have to recast to T
Related
A sample code I tried to return an instance of class is given below.
public object getConstructorclass(int i)
{
if(i==1)
{
Type type = Type.GetType("test1");
}else
{
Type type = Type.GetType("test2");
}
return Activator.CreateInstance(type);
}
var objcls = getConstructorclass(1);
objcls.callclass();//error occured
How can I mention the class type here since the type is not known at compile time but it will decided at runtime.In the above example i just pass a value 1 (it can be anything and that class will be called accordingly), and the class test1 called.
here I will get an error on the line objcls.callclass(), because objcls is an object instance that doesn't have a callclass()method.
How can I restructure this piece of code? My aim is if I mention a class in the getConstructorclass() method, an object should be returned so as to use it in the further code to invoke the members of that class.
If you know that your classes will have this method, you should use a common interface for them and implement it accordingly. Then you will work with classes that you have made sure it will work.
It would look like this
IMyInterface objcls = getconstrorclass() as IMyInterface;
if (objcls != null)
objcls.callclass();
else
// we failed miserably and should do something about it
I don't think you should use some generic object returning constructor based on an int variable, if your classes don't have anything in common. It's really weird to handle it like this and it may lead to various problems (some of which you're currently already experiencing). Generic class constructors make sense if the classes are somewhat related and you can predict the outcome, but to create a do-it-all method.. Not so sure about correctness of such approach.
Anyway, if you insist (not recommended, but as you wish), you can create some checks for a type like this:
var createdObject = getConstructorclass(1);
if (createdObject is MyClass1)
{
var specificObject = (MyClass1)createdObject;
specificObject.callMethod1();
}
else if (createdObject is MyClass2)
{
var specificObject = (MyClass2)createdObject;
specificObject.callSomeOtherMethod();
}
...
But it gets very error prone soon, refactoring will probably be a nightmare etc., but it's your call..
Or you maybe can use solution from pwas, but to me it seems unnecessarily complicated for such a basic task. Looks nice and all, but it still returns only the type "object", so it doesn't really solve your specific problem.
Also, to address one issue I'm not sure you understand - you've already created the instance, you just return type object. That is why you can't call any specific methods on this object, because first you have to cast it to something, that actually has that method and make sure the cast can be done (inheritance etc).
If interface solution (see other answers) is enough, don't look at this answer. When you can't use common base class / interface and you still want call members, you can use solution with is keyword (and check types). Instead of writing many ifs for each case, you can use fluent API:
object obj = this.getConstructorclass();
obj.StronglyInvoke()
.When<int>(value => Console.WriteLine("Got {0} as int", value))
.When<string>(value => Console.WriteLine("Got {0} as string", value))
.OnFail(() => Debug.Write("No handle."))
.Invoke();
Solution:
public class GenericCaller
{
private IList<GenericInvoker> invokers = new List<GenericInvoker>();
private readonly object target;
private Action failAction;
public GenericCaller(object target)
{
if (target == null)
{
throw new ArgumentNullException("target");
}
this.target = target;
}
public GenericCaller OnFail(Action fail)
{
this.failAction = fail;
return this;
}
public GenericCaller When<T>(Action<T> then)
{
if (then == null)
{
throw new ArgumentNullException("then");
}
var invoker = new GenericInvoker<T>(this.target, then);
this.invokers.Add(invoker);
return this;
}
public void Invoke()
{
if (this.invokers.Any(invoker => invoker.Invoke()))
{
return;
}
if (this.failAction == null)
{
throw new InvalidOperationException("Handler not found");
}
this.failAction();
}
public abstract class GenericInvoker
{
protected readonly object target;
protected GenericInvoker(object target)
{
this.target = target;
}
public abstract bool Invoke();
}
public class GenericInvoker<T> : GenericInvoker
{
private readonly Action<T> then;
public GenericInvoker(object target, Action<T> then)
: base(target)
{
this.then = then;
}
public override bool Invoke()
{
if (this.target.GetType() == typeof(T))
{
this.then((T)this.target);
return true;
}
return false;
}
}
}
public static class Extensions
{
public static GenericCaller StronglyInvoke(this object o)
{
return new GenericCaller(o);
}
}
Remeber - it would be more elegant to use common interface (as other answers say) - my is only alternative way.
Declare your variable as dynamic
dynamic objcls = getconstrorclass();
Using this the will be determined at run-time, whatever the getconstrorclass method returns. You can access any member of the type and you won't get any error at compile-time. But if you try to access a member which doesn't exists you will get a RuntimeBinderException at runtime.
I would recommend using an interface and restricting the classes that you can instantiate this way to only those that implement the interface.
public interface IMyInterface
{
void callclass();
}
public <T> getConstructorClass()
{
T instance;
Type type = Type.GetType("test1");
// instance will be null if the object cannot be cast to type T.
instance = Activator.CreateInstance(type) as T;
return T;
}
IMyInterface objcls = getConstructorClass<IMyInterface>();
if(null != objcls)
{
objcls.callclass();
}
not sure what you want to achieve in the end, but this looks like a job for "Dependency Injection" - here is a nice sample using autofac
I am having some troubles with generics and inheritance. I have an abstract class called CriteriaBase whose job it is to determine if an entity T matches the criteria defined in any sub-classes. The sub-classes have to implement a method which returns a Func representing the criteria. The problem arises when I try to use generics for the Func. Hopefully some code will illustrate my problem.
public abstract class CriteriaBase<T, U>
where T : ICrossoverable
where U : IChromosome
{
protected abstract Func<U, bool> Criteria { get; }
//some code removed for brevity
private int GetNumberOfCriteriaMatches(T season)
{
//1. works
//Func<IChromosome, bool> predicate = c => c.Genes == null;
//return season.Chromosomes.Count(predicate);
//2. doesn't work - The type arguments for method 'int
//System.Linq.Enumerable.Count<TSource>(this IEnumerable<TSource>,
//Func<TSource, bool>)'
//cannot be inferred from the usage. Try specifying the type arguments
//explicitly.
return season.Chromosomes.Count(Criteria);
}
}
My intention is that the CriteriaBase class should be generic and completely reusable.
An example sub-class:
public class TopTeamsPlayingEachOtherCriteria : CriteriaBase<Season, MatchDay>
{
//some code removed for brevity
protected override Func<MatchDay, bool> Criteria
{
get { return matchDay =>
matchDay.Fixtures.Count(
fixture =>
fixture.HomeTeam.TableGrouping.Ordering == 1
&& fixture.AwayTeam.TableGrouping.Ordering == 1) > 1; }
}
}
The problem is in the GetNumberOfCriteriaMatches() method. Option 2 is how I originally wrote the code but I get the compile error as listed. If I use option 1 then the code compiles but it means that when I override Criteria in the sub-class, I have to use IChromosome instead of MatchDay which doesn't work (I need to access specific features of a MatchDay). In my simple mind, options 1 and 2 are equivalent. Option 2 simply replaces IChromosome with a generic type U which is restricted to a class that implements IChromosome.
Is what I'm trying to achieve possible? If so, what am I missing/misunderstanding? If not, how should I approach this problem?
For completeness (included at the end as I'm not sure how much it helps with the question), here are the two entities that I'm currently using for T (Season) and U (MatchDay).
public class Season : ICrossoverable
{
private readonly IEnumerable<MatchDay> _matchDays;
public Season(IEnumerable<MatchDay> matchDays)
{
_matchDays = matchDays;
}
public IEnumerable<MatchDay> MatchDays
{
get { return _matchDays; }
}
//ICrossoverable implementation
public IEnumerable<IChromosome> Chromosomes
{
get { return _matchDays; }
}
}
public class MatchDay : IChromosome
{
private readonly int _week;
private readonly List<Fixture> _fixtures;
public MatchDay(int week, List<Fixture> fixtures)
{
_week = week;
_fixtures = fixtures;
}
//some code removed for brevity
public IEnumerable<Fixture> Fixtures
{
get { return _fixtures; }
}
//IChromosome implementation
public IEnumerable<IGene> Genes
{
get { return Fixtures; }
}
}
Well this is the problem:
public IEnumerable<IChromosome> Chromosomes
You're only declaring that you're returning a sequence of IChromosome values. Your criterion expects MatchDay values. You happen to know that it's actually returning a sequence of MatchDay values, but the compiler doesn't.
You could use Cast<> to check this at execution time:
return season.Chromosomes.Cast<U>().Count(Criteria);
... or you could change Chromosomes to return an IEnumerable<MatchDay>. Unfortunately we can't really tell whether that's a valid answer or not as we don't know how ICrossoverable is declared. Perhaps you should make ICrossoverable generic in the element type?
You should use keyword in before U in CriteriaBase definition. Something like this:
public abstract class CriteriaBase<T, in U>
where T : ICrossoverable
where U : IChromosome
Update. It will not work.
Try to specify type explicitly
private int GetNumberOfCriteriaMatches(T season)
{
....
return season.Chromosomes.Count<IChromosome>(Criteria);
}
Suppose we have an interface with a single generic method:
public interface IExtender
{
T GetValue<T>(string tag);
}
and a simple implementation A of it that returns instances of two different types (B and C) depending on the "tag" parameter:
public class A : IExtender
{
public T GetValue<T>(string tag)
{
if (typeof(T) == typeof(B) && tag == null)
return (T)(object) new B();
if (typeof(T) == typeof(C) && tag == "foo")
return (T)(object) new C();
return default(T);
}
}
is it possible to avoid the double cast (T)(object)? Or, is there a way to tell the compiler "hey, I am sure that this cast won't fail at runtime, just let me do it without first casting to object!"
Or, is there a way to tell the compiler "hey, I am sure that this cast won't fail at runtime, just let me do it without first casting to object!"
No, the language is deliberately designed to prevent this. Eric Lippert blogged about this recently. I agree it's annoying, but it does make a certain kind of sense.
To be honest, "generic" methods like this are usually a bit of a design smell. If a method has to have special cases for various different types, you should at least consider using separate methods instead. (GetB, GetC)
public T MyMethod<T>(string tag) where T : class
{
return new A() as T;
}
check this sample:
public T GetValue<T>(string tag) where T : class, new()
{
if (typeof(T) == typeof(B) && tag == null)
return new T();
if (typeof(T) == typeof(C) && tag == "foo")
return new T();
return default(T);
}
no cast needed, you can create instance of "T", just add the generic constraint that saying that T is a class and it have parameterless constructor so you don't need to create another base types and you can be sure that only suitable types will go through this generic method.
You can use dynamic to store your real result, but you have to be sure the generic argument type is the right type you return.
TResult GetResult<TResult>()
{
dynamic r = 10;
return r;
}
No, that is not possible. The only way to do so would be to let the compiler know about additional assumptions on T. As evidenced by the list of generic parameter constraints, there is no constraint defined in C# to require availability of a specific cast.
if you let B and C implement the same interface you could use a type constraint on your T. Probably not exactly what you want, but as suggested also by others what you want is not really possible.
public interface IclassBndC {}
public class B : IclassBandC {}
public class C : IclassBandC {}
public class A : IExtender
{
public T GetValue<T>(string tag) where T : IclassBandC
{
if (tag == null)
return new B();
if (tag == "foo")
return new C();
return default(T);
}
}
I'm troubleshooting a problem that I have recreated in a solution here.
The issue is that I am using some custom types that can implicitly cast from string to themselves. One of the custom types inherits from the other.
public class CustomType
{
public string InnerString { get; protected set; }
public CustomType(string s)
{
InnerString = s;
}
#region Operator Overloads
public static implicit operator CustomType(string s)
{
if (s == null)
throw new ArgumentNullException();
return new CustomType(s);
}
public static implicit operator string(CustomType value)
{
if (value == null)
return null;
return value.InnerString;
}
#endregion
}
public class SubCustomType : CustomType
{
public SubCustomType(string s)
: base(s)
{
// Nada
}
#region Operator Overloads
public static implicit operator SubCustomType(string s)
{
if (s == null)
throw new ArgumentNullException();
return new SubCustomType(s);
}
public static implicit operator string(SubCustomType value)
{
if (value == null)
return null;
return value.InnerString;
}
#endregion
}
In another generic class, I rely upon the fact that the base custom type can implicitly cast from string to itself. (The cast occurs at the line (T)this.Rtf. .Rtf is a string.) (The generic class is in my case a subclass of RichTextBox, since that's what I was using when I ran into this problem.)
public class CustomRichTextBox<T> : Forms.RichTextBox
where T : CustomType
{
public object GetValue()
{
/// This line throws:
/// InvalidCastException
/// Unable to cast object of type 'TestCustomTypesCast.CustomType' to type 'TestCustomTypesCast.SubCustomType'.
return (T)this.Rtf;
}
}
public class SubCustomRichTextBox : CustomRichTextBox<SubCustomType>
{
}
When I use SubCustomRichTextBox (an instance of the generic class that has as type argument the SUB custom type), I get an InvalidCastException at the line where I cast to T in GetValue. What I think is going on is that in order for the compiler to be okay with the fact that I am using T to cast from string, it is looking at CustomType and seeing its cast overload. But even when I use a subclass of CustomType as the actual type argument, the compiler still looks to SubCustomType.CustomType(string s) to perform the cast, and not at the correct SubCustomType.SubCustomType(string s) method.
Can anyone point me in the direction of fixing this problem? I want to use the generic class because it would allow me to reuse the same code. If I can't use generics, then I'll need to duplicate code in several subclasses of CustomRichTextBox<T>. Thanks.
It's going to be hard because the operator overload is static, and you're essentially trying to get a virtual behaviour.
Try this:
public class CustomRichTextBox<T> : Forms.RichTextBox
where T : CustomType, new()
{
public object GetValue()
{
T t = new T();
t.InnerString = this.Rtf;
return t;
}
}
Note I've added new() to the type constraint. I also had to make InnerString public settable.
As an aside, you coule make the return type of GetValue() be T. That might be a nicer API.
i'm implementing a generic interface (iqueryprovider, specifically). at some point, i'm forced to return a generic result, that i need to get from some internal interface:
public TResult Execute<TResult>(...) {
return something.Foo<TResult>();
}
where something.Foo is
public T Foo<T>() where T: MyBaseClass, new() {
...
}
this of course blows up because the externally defined TResult doesn't have the same type restrictions as the internally-defined T. the question: is there a way to make TResult palatable to Foo? can i somehow explicitly test for those two conditions and coerce the type variable?
You could try something like this:
public TResult Execute<TResult>(...)
{
if (typeof(TResult) is MyBaseClass)
{
Type mytype = typeof(TResult);
MethodInfo method = typeof({TypewhereFoo<>IsDeclared}).GetMethod("Foo");
MethodInfo generic = method.MakeGenericMethod(myType);
return (TResult)generic.Invoke(this, null);
}
else
{
// Throw here
}
}
Nope. If TResult has no constraints on it, then it can be any old thing. If your helper method cannot take any old thing, then you'll need to get a better helper method. The interface requires you to provide more services than your helper can provide, therefore, you're going to have to do the work to provide that service.
You will have to add the type restrictions to your generic method:
public TResult Execute<TResult>(...) where TResult: MyBaseClass, new() {
return something.Foo<TResult>();
}
Ouch... you have a problem. There is no way to call something.Foo() since you do not have a type that is compatible. You could 'hack' around this by creating a 'wrapper' type that is compatible to call the Foo() and then 'unwrap' :
class MyNastyFix<T> : MyBaseClass
{
public T Unwrap()
{
//assert that T has the correct base type
if (!typeof(T).IsSubclassOf(typeof(MyBaseClass)))
throw new ArgumentException();
//must use reflection to construct
T obj = (T)typeof(T).InvokeMember(null, BindingFlags.CreateInstance, null, null, null);
//cast to a type of MyBaseClass so we can copy our values
MyBaseClass c = (MyBaseClass)(object)obj;
c.SomeValue = this.SomeValue;
return obj;
}
}
public static TResult Execute<TResult>()
{
return something.Foo<MyNastyFix<TResult>>().Unwrap();
}
Update: The reflection answer might be a better approach if that works.
Change Foo to check the constraints at run-time:
public T Foo<T>() {
if (!typeof(T).IsAssignableFrom(typeof(MyBaseClass))
|| !typeof(T).GetConstructor(...))
throw new System.NotImplementedException();
...
}
The generic constraints are checked at compile-time so they can't be based on run-time conditions.