[c#] C# : Converting Base Class to Child Class

I have a class, NetworkClient as a base class :

using System.IO;
using System.Net.Sockets;
using System.Threading.Tasks;

namespace Network
{
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

public class NetworkClient
{
    public NetworkClient()
    {
        tcpClient = new TcpClient();
    }
    public NetworkClient(TcpClient client)
    {
        tcpClient = client;
    }

    public virtual bool IsConnected
    {
        get;
        private set;
    }
    private StreamWriter writer { get; set; }
    private StreamReader reader { get; set; }

    private TcpClient tcpClient
    {
        get;
        set;
    }

    public virtual NetworkServerInfo NetworkServerInfo
    {
        get;
        set;
    }

    public async virtual void Connect(NetworkServerInfo info)
    {
        if (tcpClient == null)
        {
            tcpClient=new TcpClient();
        }
        await tcpClient.ConnectAsync(info.Address,info.Port);
        reader = new StreamReader(tcpClient.GetStream());
        writer = new StreamWriter(tcpClient.GetStream());
    }

    public virtual void Disconnect()
    {
        tcpClient.Close();            
        reader.Dispose();

        writer.Dispose();
    }

    public async virtual void Send(string data)
    {
        await writer.WriteLineAsync(data);
    }

    public async virtual Task<string> Receive()
    {
        return await reader.ReadLineAsync();
    }

}
}

And also have a child class derived from NetworkClient :

using System.Net;

namespace Network
{
using Data;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

public class SkyfilterClient : NetworkClient
{
    public virtual IPAddress Address
    {
        get;
        set;
    }

    public virtual int Port
    {
        get;
        set;
    }

    public virtual string SessionID
    {
        get;
        set;
    }

    public virtual User UserData
    {
        get;
        set;
    }

    protected virtual bool Authenticate(string username, string password)
    {
        throw new System.NotImplementedException();
    }

}
}

The problem is, that when im trying to cast NetworkClient into SkyfilterClient. An exception is thrown, Unable to cast object of type 'Network.NetworkClient' to type 'Network.SkyfilterClient'.

Whats wrong with my code ? I see that Stream can be converted to NetworkStream, MemoryStream. Why NetworkClient can't be converted to Skyfilter Client?

This question is related to c# oop class

The answer is


I would recommend identifying the functionality you need from any subclasses, and make a generic method to cast into the right subclass.

I had this same problem, but really didn't feel like creating some mapping class or importing a library.

Let's say you need the 'Authenticate' method to take behavior from the right subclass. In your NetworkClient:

protected bool Authenticate(string username, string password) {
  //...
}
protected bool DoAuthenticate<T>(NetworkClient nc, string username, string password) where T : NetworkClient {
//Do a cast into the sub class.
  T subInst = (T) nc;
  return nc.Authenticate(username, password);
}

You can copy value of Parent Class to a Child class. For instance, you could use reflection if that is the case.


You can't downcast. If the parent object is created, it cannot be cast to the child.

One suggested workaround would be to Create an interface which the parent implements. Have the child override functionality if needed or just expose the parents functionality. Change the cast to be an interface and do the operations.

Edit: May be could also check if the object is a SkyfilterClient using is keyword

   if(networkClient is SkyfilterClient)
   {

   }

In OOP, you can't cast an instance of a parent class into a child class. You can only cast a child instance into a parent that it inherits from.


I'm surprised AutoMapper hasn't come up as an answer.

As is clear from all the previous answers, you cannot do the typecast. However, using AutoMapper, in a few lines of code you can have a new SkyfilterClient instantiated based on an existing NetworkClient.

In essence, you would put the following where you are currently doing your typecasting:

using AutoMapper;
...
// somewhere, your network client was declared
var existingNetworkClient = new NetworkClient();
...
// now we want to type-cast, but we can't, so we instantiate using AutoMapper
AutoMapper.Mapper.CreateMap<NetworkClient, SkyfilterClient>();
var skyfilterObject = AutoMapper.Mapper.Map<SkyfilterClient>(existingNetworkClient);

Here's a full-blown example:

  public class Vehicle
  {
    public int NumWheels { get; set; }
    public bool HasMotor { get; set; }
  }

  public class Car: Vehicle
  {
    public string Color { get; set; }
    public string SteeringColumnStyle { get; set; }
  }

  public class CarMaker
  {
    // I am given vehicles that I want to turn into cars...
    public List<Car> Convert(List<Vehicle> vehicles)
    {
      var cars = new List<Car>();
      AutoMapper.Mapper.CreateMap<Vehicle, Car>(); // Declare that we want some automagic to happen
      foreach (var vehicle in vehicles)
      {
        var car = AutoMapper.Mapper.Map<Car>(vehicle);
        // At this point, the car-specific properties (Color and SteeringColumnStyle) are null, because there are no properties in the Vehicle object to map from.
        // However, car's NumWheels and HasMotor properties which exist due to inheritance, are populated by AutoMapper.
        cars.Add(car);
      }
      return cars;
    }
  }

You can use the as operator to perform certain types of conversions between compatible reference types or nullable types.

SkyfilterClient c = client as SkyfilterClient;
if (c != null)
{
    //do something with it
}



NetworkClient c = new SkyfilterClient() as NetworkClient; // c is not null
SkyfilterClient c2 = new NetworkClient() as SkyfilterClient; // c2 is null

I don't think you can downcast an object, however there is a simple way to "downcast" the object outside the box. It isn't type safe, but it works. First serialize the object into json, then deserialize it into the child class object. It works the same as if you were passing the object between apis. So, while there are some people who may say "this doesn't work or isn't good", I would argue that it is exactly the way our internet currently works, so... why not use that method? No mapping required as long as parameter names are the same, and they will be if it is a child class. Note: This will likely not copy any private fields; if you have a constructor with parameters, this probably needs to be tested as well to ensure there aren't side effects.

Here's my toolbox:

public static string ConvertToJson<T>(this T obj)
{
    return JsonConvert.SerializeObject(obj);
}
public static T ConvertToObject<T>(this string json)
{
    if (string.IsNullOrEmpty(json))
    {
        return Activator.CreateInstance<T>();
    }
    return JsonConvert.DeserializeObject<T>(json);
}

Here's how to use it:

var sfcl = networkClient.ConvertToJson().ConvertToObject<SkyfilterClient>();

If you HAVE to, and you don't mind a hack, you could let serialization do the work for you.

Given these classes:

public class ParentObj
{
    public string Name { get; set; }
}

public class ChildObj : ParentObj
{
    public string Value { get; set; }
}

You can create a child instance from a parent instance like so:

var parent = new ParentObj() { Name = "something" };
var serialized = JsonConvert.SerializeObject(parent);
var child = JsonConvert.DeserializeObject<ChildObj>(serialized);

This assumes your objects play nice with serialization, obv.

Be aware that this is probably going to be slower than an explicit converter.


Use the cast operator, as such:

var skyfilterClient = (SkyfilterClient)networkClient;

There's a few ways of doing this. However, here is one of the easiest ways to do this and it's reusable.

What is happening is that we're getting all the properties of the parent class and updating those same properties on the child class. Where baseObj would be the parent object and T would be the child class.

public static T ConvertToDerived<T>(object baseObj) where T : new()
    {
        var derivedObj = new T();
        var members = baseObj.GetType().GetMembers();
        foreach (var member in members)
        {
            object val = null;
            if (member.MemberType == MemberTypes.Field)
            {
                val = ((FieldInfo)member).GetValue(baseObj);
                ((FieldInfo)member).SetValue(derivedObj, val);
            }
            else if (member.MemberType == MemberTypes.Property)
            {
                val = ((PropertyInfo)member).GetValue(baseObj);
                if (val is IList && val.GetType().IsGenericType)
                {
                    var listType = val.GetType().GetGenericArguments().Single();
                    var list = (IList)Activator.CreateInstance(typeof(List<>).MakeGenericType(listType));
                    foreach (var item in (IList)val)
                    {
                        list.Add(item);
                    }
                    ((PropertyInfo)member).SetValue(baseObj, list, null);
                }
                if (((PropertyInfo)member).CanWrite)
                    ((PropertyInfo)member).SetValue(derivedObj, val);
            }
        }
        return derivedObj;
    }

Examples related to c#

How can I convert this one line of ActionScript to C#? Microsoft Advertising SDK doesn't deliverer ads How to use a global array in C#? How to correctly write async method? C# - insert values from file into two arrays Uploading into folder in FTP? Are these methods thread safe? dotnet ef not found in .NET Core 3 HTTP Error 500.30 - ANCM In-Process Start Failure Best way to "push" into C# array

Examples related to oop

How to implement a simple scenario the OO way When to use 'raise NotImplementedError'? PHP: cannot declare class because the name is already in use Python class input argument Call an overridden method from super class in typescript Typescript: How to extend two classes? What's the difference between abstraction and encapsulation? An object reference is required to access a non-static member Java Multiple Inheritance Why not inherit from List<T>?

Examples related to class

String method cannot be found in a main class method Class constructor type in typescript? ReactJS - Call One Component Method From Another Component How do I declare a model class in my Angular 2 component using TypeScript? When to use Interface and Model in TypeScript / Angular Swift Error: Editor placeholder in source file Declaring static constants in ES6 classes? Creating a static class with no instances In R, dealing with Error: ggplot2 doesn't know how to deal with data of class numeric Static vs class functions/variables in Swift classes?