简体   繁体   中英

How to branch code based on class data type

I am attempting to implement some more complex data structures in c# working with no libraries other than System. Currently i am working on graphs.

I have created 3 classes already to represent nodes, directed edges, and undirected edges. Each of these can have a different data type eg node<string> will be a node with information stored as a string and directedEdge<string> will link nodes that store strings.

My graph class is declared as Graph<dataType, edgeType> (for now I am assuming all edges in a single graph are the same type), and I would like to branch within this class based on whether a directed or undirected edge is being used. The code bellow does not work, but explains the functionality I would like to achieve.

if (edgeType == directedEdge<dataType>)
{

}
else if (edgeType == undirectedEdge<dataType>)
{

}
else
{

}

Is there any way to implement something like what is shown above? If so, how?

Well you could use pattern matching:

switch (edge)
{
    case directedEdge<dataType> de:
        // Do whatever..
        break;
    case undirectedEdge<dataType> ue:
        // Do whatever..
        break;
    default:
        // Do whatever..
        break;
}

In the above example edge is an actual instance, not a type.

But this might not be the best design to implement, because as you introduce new edge types, you will need to update the switch statement also.

If you do this in multiple places, the effects are amplified.

A better way, following OOP principles, would be to define the behaviour in the edge types themselves:

abstract class Edge
{
    abstract void DoSomething();
}

class directedEdge<T> : Edge
{
    override void DoSomething() { }
}

class undirectedEdge<T> : Edge
{
    override void DoSomething() { }
}

then in your method, its simply:

Edge edge = // Some specific edge type
edge.DoSomething();

There are several ways to do this, following the evolution of C# over the years.

  • Check runtime type

     Edge<int> edge = GetEdge(1); if (edge.GetType() == typeof(DirectedEdge<int>)) { } else if(edge.GetType() == typeof(UnidirectedEdge<int>)) { }
  • Use casting with the as keyword

     Edge<int> edge = GetEdge(1); DirectedEdge<int> directed_edge = edge as DirectedEdge<int>; if (directed_edge != null) { // Use directed_edge } else { UnidirectedEdge<int> uni_edge = edge as UnidirectedEdge<int>; if (uni_edge != null) { // Use uni_edge } }
  • Use pattern matching if statements

     Edge<int> edge = GetEdge(1); if (edge is DirectedEdge<int> directed_edge) { // Use directed_edge } else if (edge is UnidirectedEdge<int> uni_edge) { // Use uni_edge }
  • Use pattern matching switch statement

     Edge<int> edge = GetEdge(1); switch (edge) { case DirectedEdge<int> directed_edge: // Use directed_edge case UnidirectedEdge<int> uni_edge: // Use unit_edge default: throw new NotSupportedException(); }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM