Share via

Compilation Error CS8625 - C#

Anshul Khandelwal 20 Reputation points
2023-10-02T02:38:40.7466667+00:00

Why the below code snippet giving compilation error, all the sub classes has been passed correctly:

https://stackoverflow.com/questions/77191924/below-code-is-giving-error-error-cs1503-argument-1-cannot-convert-from-chil
abstract class Test<A,B> {

   private  Test<B,object> t1;

    public Test(Test<B, object> t) {
        t1 = t;
    }

}

class Child1 : Test<int, string>
{
    public Child1(Test<string, object> t) : base(t)
    {

    }
}


class Child2 : Test<string,bool>
{
    public Child2(Test<bool, object> t) : base(t)
    {

    }
}

class Achild1
{

    public Achild1(object obj)
    {

    }
}




class Main
{
    public void Init()
    {
        Child2 c2 = new Child2(null);
        Child1 c1 = new Child1(c2);
    }

}


Developer technologies | C#
Developer technologies | C#

An object-oriented and type-safe programming language that has its roots in the C family of languages and includes support for component-oriented programming.


Answer accepted by question author

KOZ6.0 6,810 Reputation points
2023-10-04T08:48:08.4566667+00:00

In short, the problem is solved if Test<A, B> behaves as Test<A, object>. .NET Framework has the RealProxy class. It is mainly used in AOP. With this, you can create a transparent proxy and treat Test<A, B> as Test<A, object>.

First, in order to create a transparent proxy, the Test<A, B> class must be a class that inherits MarshalByRefObject. Then, declare that implicit type conversion is possible. The content is transparent proxy creation processing.

abstract class Test<A, B> : MarshalByRefObject
{
    public A ValueA { get; set; }   
    public B ValueB { get; set; }

    private Test<B, object> t1;

    protected Test(Test<B, object> t) {
        t1 = t;
        ValueA = default(A);
        if (t != null) {
            ValueB = t.ValueA;
        }
    }

    public static implicit operator
            Test<A, object>(Test<A, B> value) {
        return UTL.CreateProxy(value);
    }
}

Next, inherit the RealProxy class and create a class to create a transparent proxy. Convert Test<A, object> method to Test<A, B> method with Invoke method and execute.

using System;
using System.Collections.Generic;
using System.Reflection;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Messaging;
using System.Runtime.Remoting.Proxies;
using System.Diagnostics;

static class UTL
{
    public static Test<A, object> CreateProxy<A, B>(Test<A, B> test) {
        var proxy = new TestProxy<A, B>(test);
        return (Test<A, object>)proxy.GetTransparentProxy();
    }

    internal abstract class TestProxy : RealProxy
    {
        protected Type proxyType;
        protected TestProxy(Type classToProxy) 
            : base(classToProxy) { 
            proxyType = classToProxy;
        }
        public abstract object Instanse { get; }
    }

    internal class TestProxy<A, B> : TestProxy
    {
        public override object Instanse => instance;

        private readonly Test<A, B> instance;
        private readonly Type instanceType;
        private readonly Dictionary<MethodInfo, MethodInfo> mappings
            = new Dictionary<MethodInfo, MethodInfo>();
        const BindingFlags bindingFlags
                                = BindingFlags.Public | BindingFlags.Instance;

        public TestProxy(Test<A, B> instance)
            : base(typeof(Test<A, object>)) {

            this.instance = instance;
            instanceType = instance.GetType();

            // Should be same.
            MethodInfo[] proxyMethods = proxyType.GetMethods(bindingFlags);
            MethodInfo[] instanceMethods = instanceType.GetMethods(bindingFlags);
            for (int i =  0; i < instanceMethods.Length; i++) {
                if (proxyMethods[i].Name != instanceMethods[i].Name) {
                    throw new InvalidProgramException();
                }
                mappings.Add(proxyMethods[i], instanceMethods[i]);
            }
        }

        public override IMessage Invoke(IMessage msg) {
            try {
                IMethodMessage mm = msg as IMethodMessage;
                object[] args = mm.Args;
                MethodInfo proxyMethod = (MethodInfo)mm.MethodBase;
                object ret = InvokeToInstance(proxyMethod, args);
                return new ReturnMessage(ret, args, args.Length,
                    mm.LogicalCallContext, (IMethodCallMessage)msg);
            } catch (Exception ex) {
                if (ex.InnerException != null) {
                    return new ReturnMessage(ex.InnerException, (IMethodCallMessage)msg);
                }
                return new ReturnMessage(ex, (IMethodCallMessage)msg);
            }
        }

        private object InvokeToInstance(MethodInfo proxyMethod, object[] args) {
            if (mappings.TryGetValue(proxyMethod, out MethodInfo instanceMethod)) {
                return instanceMethod.Invoke(instance, args);
            }
            // Field Get/Set
            string fieldName = (string)args[1];
            FieldInfo fi = instanceType.GetField(fieldName);
            switch (proxyMethod.Name) {
                case "FieldSetter":
                    fi.SetValue(instance, args[2]);
                    break;
                case "FieldGetter":
                    args[2] = fi.GetValue(instance);
                    break;
                default:
                    throw new InvalidProgramException("InvokeToInstance");
            }
            return null;
        }
    }
}

Unfortunately, it was deleted in .NET, and DispatchProxy class added, but since it is interface-based, it is not as easy to use as RealProxy, which is a real shame.

Let's try using it. You should see that Test<A, B> behaves like Test<A, object>.

static void Main(string[] args) {
    Child3 c3 = new Child3(null);
    c3.ValueA = true;
    c3.ValueB = 1;
    Test<bool, object> proxy = c3;
    bool valueA = proxy.ValueA;
    object valueB = proxy.ValueB;
    Child2 c2 = new Child2(c3);
    Child1 c1 = new Child1(c2);
}

Was this answer helpful?


3 additional answers

Sort by: Most helpful
  1. Anshul Khandelwal 20 Reputation points
    2023-10-03T20:36:35.1866667+00:00

    I got one solution on Stackoverflow which works fine, but I am still stuck on the return statement:

    interface ITest<out A, out B>
    {
        // Covariant interface with no members that use A or B in input positions.
    }
    
    
    abstract class Test<A, B> : ITest<A, B>
    {
        private ITest<B, object> t1;
    
        protected Test(ITest<B, object> t)
        {
            t1 = t;
        }
    
        // Additional functionality for the Test class could be added here.
    }
    
    
    class Child1 : Test<int, string>
    {
        public Child1(ITest<string, object> t) : base(t)
        {
        }
    
        // Additional functionality for the Child1 class could be added here.
    }
    
    class Child2 : Test<string, bool>, ITest<string, object> // Explicitly implementing the needed interface
    {
        public Child2(ITest<bool, object> t) : base(t)
        {
        }
    
        // Additional functionality for the Child2 class could be added here.
    }
    class Child3 : Test<bool, int>, ITest<bool, object>
    {
        public Child3(Test<int,object> t): base(t) { }
    }
    
    
    
    
    
    
    class Main
    {
        public Test<int,object> definedTest() {
    
            Child3 c3 = new Child3(null);
            Child2 c2 = new Child2(c3);
            Child1 c1 = new Child1(c2);
             return c1;//<-- this is giving me error, here I wanted to return the generic return type with parent class.
           }
        public static void main(String[] args)
        {
            Main m = new Main();
            m.definedTest();
            
    
        }
    }
    
    

    Was this answer helpful?


  2. KOZ6.0 6,810 Reputation points
    2023-10-02T23:13:39.0866667+00:00
    abstract class Test<A,B> {
    
        private final Test<B,?> t1;
    
        public Test(Test<B, ?> t) {
            t1 = t;
        }
    }
    

    ? is third generic. Then C# will look like this

    abstract class Test<A, B, C> 
    {
        protected Test<B, C, object> t1;
        public Test(Test<B, C, object> t) {
            t1 = t;
        }
    }
    

    Adjust it well...

    class Child1 : Test<int, string, bool>
    {
        public Child1(Test<string, bool, object> t) : base(t) { }
    }
    
    class Child2 : Test<string, bool, object>
    {
        public Child2(Test<bool, object, object> t) : base(t) { }
    }
    

    did it?

    static void Main() {
    	Child2 c2 = new Child2(null);
    	Child1 c1 = new Child1(c2);
    }
    

    Was this answer helpful?


  3. Bruce (SqlWork.com) 84,086 Reputation points
    2023-10-02T15:59:48.4966667+00:00

    in your case:

    var t1 = new Test<bool, object>(); 
    var t2 = Test<string,bool>();
    var t3 = (Test<bool, object>) = t2;  // compile error
    

    t2 can not be cast to Test<bool, object>, because it does not inherit from Test<bool,object>, it inherited from (Test<A,B>)

    sample without genetics:

    public class MyBase{}
    public class MyClass1 : MyBase {}
    public class MyClass2 : MyBase {}
    
    ...
    
    var test1 = new MyClass1();
    var test2 = (MyClass2) test1;  // error can not cast MyClass2 to MyClass1
    var test3 = (MyBase) test1;    // works
    

    Was this answer helpful?


Your answer

Answers can be marked as 'Accepted' by the question author and 'Recommended' by moderators, which helps users know the answer solved the author's problem.