Home > Software design >  C# Cannot convert from CResourceGroup to TResource
C# Cannot convert from CResourceGroup to TResource

Time:09-30

I have extracted this from the real code and just implemented some things to give it context (I hope). I get the following error on the line with the recursive call to GetResourceVariable

CS1503: Argument 1: cannot convert from `CResourceGroup` to `TResource` 
Argument type `CResourceGroup` is not assignable to parameter type `TResource`

What I am trying to do is call GetResourceVariable on an object of type TResource to get a certain variable value. These objects are part of a hierarchy so if the variable is not defined on the resource I want to traverse up the hierarchy and see whether a 'parent' has this variable defined and return that value. This is where FromResource comes in. Now this FromResource should a group/folder type resource, but that has much of the properties of a resource, which you can see from the class inheritance hierarchy.

I don't get why I can't use a CResourceGroup (which is a CResDefs which is a CResource as the parameter to the generic function that has a where TResource : CResource I thought that the where constraint meant that only objects that are CResource (or inherited from CResource) could be the parameter? Somehow this last part seems not true!

I might be able to refactor the inheritance hierarchy but before trying that I would rather know why this is not possible as shown in C#?

using System;
using System.Collections.Generic;

public class Program
{
    public class CResVariable 
    { 
      public string Value { get; set; }
    }

    public class CResVariableList : List<CResVariable> 
    {
        public CResVariable GetByName(string name) { return null; }
    }

    public class CResource {
        public CResVariableList ResVariables { get; set; }
        public CResourceGroup FromResource
        {
            get
            {
                return this.GetFromResource(useChildrenList:true);
            }
        }
        protected CResourceGroup GetFromResource(bool useChildrenList = false)
        { 
            return null;
        }
    }

    public class CResDefs : CResource {}

    public class CResourceGroup : CResDefs {}
    
    public class ResVariableSupport {
        public string GetResourceVariable<TResource>(TResource resource, string variableName, bool recursive)
            where TResource : CResource
            {
                CResVariable variable = resource?.ResVariables?.GetByName(variableName);
                if (variable != null)
                {
                    return variable.Value;
                }
                if (recursive)
                {
                    return this.GetResourceVariable<TResource>(resource?.FromResource, variableName, true);
                }
                return "";
            }
    }

    public static void Main() {
        Console.WriteLine("Hello world!");
    }
}

CodePudding user response:

The only problem in your code is explicitly naming the generic parameter in the call to GetResourceVariable - you dont need to do that as it is implied from the call.

This works:

return this.GetResourceVariable(resource?.FromResource, variableName, true);

Code here: https://dotnetfiddle.net/LxUIxL

  • Related