Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C#: Assign child class instance to interface implemented by abstract class

Tags:

c#

oop

public interface IParser<T> where T: new()
{
    IList<T> Parse();
}

Above interface is implemented by following abstract class

public abstract class BaseParser<T>: IParser<T> where T : new()
{
   protected abstract string Sql { get;}
   public List<T> Parse()
   {
      // do parsing
      Console.WriteLine(Sql);
   }
}

Following are two concrete implementation of above abstract class

public class EMailParser: BaseParser<Email>
{
    protected override string Sql
    {
        get
        {
            return @"SELECT * FROM emails";
        }
    }
}

public class UrlParser : BaseParser<Url>
{
    protected override string Sql
    {
        get
        {
            return @"SELECT * From Url";
        }
    }
}

Usage:

class Program
{
    static void Main(string[] args)
    {
       if(args[1] == "url")
          Parser<Url>();
       else
          Parser<Email>();
    }
    static void Parse<T>()
    {
       // Create instance based on typof T and then assign to implementaion
       IParser<T> parser = typeof(T) == typeof(Url) ? new UrlParser(): new EmailParser();
       parser.Parse();
    }
}

I want to create instance of EmailParser or UrlParser base on generic type provided in Program.Main method and assign it to interface implemented by BaseParser (abstract class). How can I do this? I know i can solve this problem by modifying Program.Parse<T> as following

static void Parse<T>() where T: new()
{
    IParser<T> parser = typeof(T) == typeof(Url) ? new UrlParser() as BaseParser<T> : new EmailParser() as BaseParser<T>;
    parser.Parse();
}

However I want to know why I can't assign child class instance to interface implemented by abstract class??

I can't understand why following line does not work

IParser<T> parser = typeof(T) == typeof(Url) ? new UrlParser(): new EmailParser();

and why this line work

IParser<T> parser = typeof(T) == typeof(Url) ? new UrlParser() as BaseParser<T> : new EmailParser() as BaseParser<T>;

As per @nawfal answer this line also should not work because BaseParser and BaseParser are different types. Does there exists implicit case for IParser from BaseParser?

like image 477
Zeeshan Avatar asked Mar 13 '23 00:03

Zeeshan


1 Answers

I believe the issue is that the compiler doesn't consider the type to which you are assigning the result of the ?: conditional when parsing the conditional. Rather, the ?: is parsed in isolation, so the compiler can't figure out which type to use.

Edit: From section 7.14 of the C# 5.0 specification:

The second and third operands, x and y, of the ?: operator control the type of the conditional expression. If x has type X and y has type Y then:

  • If an implicit conversion (§6.1) exists from X to Y, but not from Y to X, then Y is the type of the conditional expression.

  • If an implicit conversion (§6.1) exists from Y to X, but not from X to Y, then X is the type of the conditional expression.

  • Otherwise, no expression type can be determined, and a compile-time error occurs.

like image 200
wablab Avatar answered May 04 '23 09:05

wablab