Search code examples
c#type-constraints

How to abstract operation from unrelated types?


REMARK after rethinking my issue. Though the best solution for my exact example with WriteData method was proposed by @Dogu Arslan, the issue in question's title was actually solved by @InBetween and @Fabio. I. e. for my exact example with WriteData method it is better to move the conversion logic out of WriteData method, but to abstract the logic from unrelated types it is better to use proposed overloading. So all the three answers are helpful for me.

I already have read the following similar questions - 1, 2, and others - but not have come with something suitable solution in my case.

My case is: I have the following simple method. The important part is the line with commentary and the "source" parameter. The rest part is not so important and serves only to show that there is an "operation" from the question's title.

void WriteData(
    int count, 
    int currentIndex, 
    List<byte> source, 
    StreamWriter sw, 
    string fileName)
{
    var countToWrite = count - currentIndex;

    if (countToWrite == 0)
        return;

    if (sw == null)
        sw = new StreamWriter(GetFullPath(fileName));

    //---------- Source's elements must be converted to string.
    var dataToWrite =
        source.GetRange(currentIndex, countToWrite)
        .Select(x => Convert.ToString(x));

    StringBuilder sb = new StringBuilder();

    foreach (var item in dataToWrite)
        sb.AppendLine(item);

    sw.Write(sb.ToString());
}

For now I want the "source" parameter to be list with bytes, or doubles, or strings. Have I write three copies of WriteData method with only single change - the type of list in "source"? Or there is a better approach?

I tried type constraint, but to what type to constrain?

I tried to check the type and to throw exceptions if it is not in my type list (byte, double, string). But exceptions work only at run-time, and I want it to work in compile-time.

For now I have to restrict myself with run-time type checking as temporary solution, but, as I mentioned before, it is not suitable in perspective.


Solution

  • One thing you could do is to remove the string conversion responsibility to another class altogether.ie. StringConverter class which would have overloaded constructors that would take these different input types to convert them to string and provide a method that returns a string. That way even if you extend in future the types you support you would not need to change this method here in your example, all of that would be transparent behind you string converter class. The checks will also be compile time because string converter class would take the input through its constructor. Yes this would mean everytime you want to call WriteData method you would need to instantiate a new StringConverter object but C# does not provide type constraints on the level you ask out of the shelf.