2017-04-18 20 views
0

备注重新考虑我的问题后。 尽管我的WriteData方法的确切示例的最佳解决方案是由@Dogu Arslan提出的,但问题标题问题实际上是由@InBetween和@Fabio解决的。 I. e。对于使用WriteData方法的确切示例,最好将WriteData方法中的转换逻辑移出,但为了从不相关类型中提取逻辑,最好使用建议的重载。所有这三个答案对我都有帮助。如何从无关的类型抽象操作?

我已经阅读了以下类似的问题 - 1,2和其他 - 但没有在我的情况下提供适合的解决方案。

我的情况是:我有以下简单的方法。重要的部分是带有注释和“源”参数的行。其余部分并不重要,仅用于表明问题标题中存在“操作”。

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()); 
} 

现在我想要“源”参数与字节,或双打或字符串列表。我有没有写WriteData方法的三个副本只有一个更改 - “源”中的列表类型?或者有更好的方法?

我试过类型约束,但是要约束什么类型?

我试着检查类型并抛出异常,如果它不在我的类型列表中(字节,双精度,字符串)。但是异常只在运行时才起作用,我希望它能在编译时工作。

现在我必须限制自己的运行时类型检查作为临时解决方案,但是,正如我之前提到的,它不适合从视角来看。

+0

你可以使它通用,并检查它是否以编程方式给出类型/ –

回答

1

有一件事你可以做的是去除字符串转换责任到其他类altogether.ie。 StringConverter类,它会重载构造函数,它们会将这些不同的输入类型转换为字符串并提供返回字符串的方法。这种方式即使你将来扩展你所支持的类型也不需要在你的例子中改变这个方法,所有这些在你的字符串转换器类后面都是透明的。检查也将是编译时间,因为字符串转换器类将通过其构造函数接受输入。是的,这意味着每次你想要调用WriteData方法时,你都需要实例化一个新的StringConverter对象,但是C#没有在你问的层面上提供类型约束。

+0

我同意你的意见。尽管InBetween和Fabio也提出了很好的解决方案,但我认为最好的方法是将转换逻辑移出WriteData方法。 – Alex34758

3

为什么不使用同一个重载方法“墙根”实际的解决方案

public void WriteData(List<byte> source) { WriteData<byte>(source); } 
public void WriteData(List<double> source) { WriteData<double>(source); } 
public void WriteData(List<string> source) { WriteData<string>(source); } 

private void WriteData<T>(List<T> source) 
{ 
    // Your actual implementation 
} 

在私有方法,你可以检查类型和抛出异常,当错误类型给出,万一你想“保护”作出私有方法公众通过“错误”。

+0

抛出异常与运行时有关,但我想要一个编译时错误或警告。 – Alex34758

+1

@ Alex34758,抛出异常只是一层“保护”。公开的重载与显式声明的类型为您提供编译时检查 – Fabio

+0

您的解决方案对我确切的问题很有帮助,但我同意@DoguArslan必须重新考虑问题,并且最好从WriteData方法中移除转换逻辑(我会在调用WriteData方法之前先用Convert类转换“source”,然后将结果作为“source”参数传递,类型将为List ),这样问题就会被消除。正确的架构是关键。 – Alex34758

2

最好的办法是公开暴露需要重载然后委托执行私人泛型方法:

public void WriteData(, , List<string> source, ,) { WriteData<string>(...); } 
public void WriteData(, , List<byte> source, ,) { WriteData<byte>(...); } 
public void WriteData(, , List<double> source, ,) { WriteData<double>(...); } 

private void WriteData<T>(, , List<T> source, ,) 
{ 
    Debug.Assert(typeof(T).Equals(typeof(string)) || 
       typeof(T).Equals(typeof(byte)) || 
       typeof(T).Equals(typeof(double))); 
    ... 
} 
+0

哦,你这样做@Fabio呢。但是,如果在公共WriteData方法中列表元素的显式类型已经限制泛型类型T,为什么要使用Debug.Assert?看来Debug.Assert永远不会有“假”的情况。 – Alex34758

+2

@ Alex34758因此'Debug.Assert'不是'throw'无论什么异常。在你的班级以外,没有人会*以无效的方式打电话(禁止反思),但是没有任何东西可以阻止你班上*的无效呼叫。断言是作为一个安全网。 – InBetween

+0

你的解决方案对我确切的问题很有帮助,但我同意@DoguArslan认为这个问题必须重新考虑,并且最好从WriteData方法中移除转换逻辑(我将在调用之前将Convert类转换为“源” WriteData方法,然后将结果作为“源”参数传递,该类型将为列表),因此问题将被消除。正确的架构是关键。 – Alex34758