简体   繁体   English

设计具有类似功能但返回类型不同的方法

[英]Designing methods with similar functionality but different return types

I am writing a class that parses text from a given file. 我正在编写一个解析给定文件中的文本的类。 There are a few different "types" of text, and the parsing rules differ for each. 文本有一些不同的“类型”,解析规则各有不同。

For example, one type of text, we will just call "Plain Text", is a simple string for which the parser strips out extra whitespace. 例如,一种类型的文本,我们将只调用“纯文本”,是一个简单的字符串,解析器会删除额外的空格。 So for example, if I had "The quick brown fox\\r\\njumped over the lazy brown dogs\\r\\n" , the parser would simply just return "The quick brown fox jumped over the lazy brown dogs" (line breaks converted to single spaces). 因此,例如,如果我有"The quick brown fox\\r\\njumped over the lazy brown dogs\\r\\n" ,解析器只会返回"The quick brown fox jumped over the lazy brown dogs" (换行符转换为单个空间)。

Other text is representative of a table with a given delimiter, so it may look like "First Name,Last Name,DOB" , and the parser's job is to return an array containing each comma-separated value. 其他文本代表具有给定分隔符的表,因此它可能看起来像"First Name,Last Name,DOB" ,并且解析器的工作是返回包含每个逗号分隔值的数组。

(The actual implementation is more complex than this but this is a good simplification). (实际实现比这更复杂,但这是一个很好的简化)。

Originally I was going to go about this by creating an enum named something like TextType , with values PlainText and TableText . 最初我打算通过创建一个名为TextType的枚举来实现这个TextType ,其值为PlainTextTableText Then I could have a method that would look like 然后我可以有一个看起来像的方法

public string ParseText(string textToParse, TextType textType)

I quickly realized this doesn't work because when textType is PlainText the return value should be a string , but when textType is TableText the return value should be a string[] . 我很快意识到这不起作用,因为当textType是PlainText时,返回值应该是一个string ,但是当textType是TableText时,返回值应该是一个string[]

One option would be to always return a string[] and just have it as a given that PlainText will always return an array of size 1. I'm not too thrilled with this though because it just doesn't seem semantically correct and could be confusing. 一种选择是始终返回一个字符串[],并将它作为一个给定,PlainText将始终返回一个大小为1的数组。虽然因为它似乎在语义上看起来不正确而且可能是混乱。

Another option would be to write a method for each TextType, so I could have 另一个选择是为每个TextType编写一个方法,所以我可以

public string ParsePlainText(string textToParse)

and

public string[] ParseTableText(string textToParse)

The reason I don't like this approach is because it removes some of the flexibility provided by the original approach with the enum. 我不喜欢这种方法的原因是因为它消除了原始方法与枚举提供的一些灵活性。 For example, it's expected that I will be adding additional text types later; 例如,我预计稍后会添加其他文本类型; in the future I might have a type of text that the client wishes to identify as say, HeadingText, but will be parsed the same way as plain text. 在将来,我可能会有一种客户希望识别为HeadingText的文本,但将以与纯文本相同的方式进行解析。 With the original approach, the public interface of the class containing the parsing method wouldn't have to change, because I could just add a new value to the TextType enum and modify the internals of the ParseText method. 使用原始方法,包含解析方法的类的公共接口不必更改,因为我可以向TextType枚举添加新值并修改ParseText方法的内部。 Additionally I think it's just a much cleaner interface when there is only one method to call, and the client simply has to pass the TextType (which he knows) and everything else is handled for him (versus having to pick from a list of similarly named methods that grows each time a new text type is added). 另外,我认为只有一种方法可以调用,它只是一个更清晰的界面,客户端只需要传递TextType(他知道)并为他处理其他所有事情(而不是从类似命名的列表中选择)每次添加新文本类型时增长的方法)。

Finally I could just return an object that both string and string[] inherit from (since this is C#, I can just return object ), and have the client cast to the appropriate type. 最后我可以返回一个stringstring[]继承的对象(因为这是C#,我只能返回object ),并让客户端转换为适当的类型。 I think this is the worst approach of all because it requires the client to know what should "actually" be returned, and has a huge potential for someone breaking every dependency by changing a type returned from the Parse class and not encountering resulting errors until runtime (since there's essentially no type checking to begin with). 我认为这是所有方法中最糟糕的方法,因为它要求客户端知道应该“实际”返回什么,并且通过更改从Parse类返回的类型并且直到运行时才遇到结果错误,有很大的可能性来破坏每个依赖项(因为基本上没有类型检查开始)。

Is there a "right" or optimal approach for this situation? 对于这种情况,是否存在“正确”或最佳方法?

There's a few ways.. but the first that comes to mind is using interfaces : 有几种方法..但首先想到的是使用interfaces

interface ITextParser {
    string Parse(string text);
}

public class TableTextParser : ITextParser {
    public string Parse(string text) {
        // specific table parsing stuff here
    }
}

public class PlainTextParser : ITextParser {
    public string Parse(string text) {
        // specific plain text parsing stuff here
    }
}

Your main function could then become a factory of sorts, like this: 您的主要功能可能会成为各种工厂,如下所示:

public ITextParser CreateParserFor(string textToParse) {
    // logic here to determine the sort of parser you require:
    if (typeOfTextIsTable)
        return new TableTextParser();

    if (typeOfTextIsPlain)
        return new PlainTextParser();
}

Then you can perhaps call it like so: 然后你可以像这样称呼它:

var parser = CreateParserFor(string_here);
var result = parser.Parse(string_here);

Let's try to clarify the problem a bit. 让我们试着澄清一下这个问题。 You have two types of texts (at least for now, that will likely grow to more types), that: 您有两种类型的文本(至少现在,可能会增长到更多类型),即:

  1. Have the same input type, String. 具有相同的输入类型,String。
  2. Have different output types, String and an Array. 有不同的输出类型,String和Array。
  3. Have different implementation. 有不同的实施。

The future added types may require a different types of output/return. 未来添加的类型可能需要不同类型的输出/返回。 Now the question is, is it really logical to try to combine these functionality into one method? 现在的问题是,尝试将这些功能组合到一个方法中是否合乎逻辑? I see that your goal is to provide a uniform/generic interface to the clients, but, if the the return types are different, I am not sure if you can provide such an interface. 我看到你的目标是为客户端提供统一/通用的接口,但是,如果返回类型不同,我不确定你是否可以提供这样的接口。

I don't think having many similar methods in an interface is a bad thing. 我不认为在界面中有很多类似的方法是件坏事。 There are many well-known libraries that are this way. 这种方式有许多着名的图书馆。

In my opinion, your second approach, having something like 在我看来,你的第二种方法,有类似的东西

public string ParsePlainText(string textToParse)
public string[] ParseTableText(string textToParse)

despite your suspicion, is a much cleaner way, than the other suggested ways. 尽管你怀疑,但是比其他建议的方式更清洁。 Especially, if you look at it from the clients view (compared to case where an array of size 1 is return, or casting used, etc). 特别是,如果从客户端视图中查看它(与返回大小为1的数组或使用转换等的情况相比)。

For any of the approaches suggested, you could return a ParseResults object from the Parse method representing a collection of results. 对于建议的任何方法,您可以从表示结果集合的Parse方法返回ParseResults对象。 This can then expose an iterator to iterate through the ParseResults . 然后,这可以暴露iterator以迭代ParseResults

This keeps your signature uniform and IMO does not confuse. 这使您的签名保持统一,IMO不会混淆。

Hope this helps. 希望这可以帮助。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 当我们的类具有类似的高级功能但在方法中返回不同类型时,使用哪种设计模式? - Which design pattern to use when we have classes that does similar high level functionality but the returns different types in methods? 具有不同返回类型的相同方法 - Same methods with different return types 返回不同返回类型的方法 - methods that are returning different return types 具有不同返回类型的操作方法的相同名称 - Same Name For Action Methods With Different Return Types 我可以调用执行类似功能的不同类(使用不同的方法和类型)吗? - May I call different classes (with different methods and types) that perform similar functions? 我应该在重载方法上使用不同的返回类型吗? - Should I use different return types on overloaded methods? 多个异步方法,最好使用WhenAll具有不同的返回类型 - Multiple Async Methods, best to use WhenAll with different return types 路径方法和返回类型 - Pathing methods and return types 方法的返回类型的目的 - Purpose of return types for methods 如何为功能几乎相同但参数和返回类型不同的一组类创建接口? - How can I create an interface for a set of classes with almost identical functionality but with different parameters and return types?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM