Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/typo3/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 用于实现的常量字符串的最佳实践_C#_String_Oop_Design Patterns_Interface - Fatal编程技术网

C# 用于实现的常量字符串的最佳实践

C# 用于实现的常量字符串的最佳实践,c#,string,oop,design-patterns,interface,C#,String,Oop,Design Patterns,Interface,假设我有一个界面: public interface IFeature { Task execFeature(); } 和两个实现: public class FirstFeature : IFeature { private IWebApi webApi; public FirstFeature(IWebApi webApi) { this.webApi = webApi; } public async Task execFe

假设我有一个界面:

public interface IFeature
{
    Task execFeature();
}
和两个实现:

public class FirstFeature : IFeature
{
    private IWebApi webApi;
    public FirstFeature(IWebApi webApi)
    {
        this.webApi = webApi;
    }

    public async Task execFeature()
    {
        string response = await webApi.getClassName();
        IResult result;
        if(response==null)
            result = new TextResult("Error accessing api - check internet connection/api address");
        else
            result = new TextResult("Hello dear user – the selected class name is " + response);
        result.display();
    }
}

public class SecondFeature : IFeature
{
    private IWebApi webApi;
    public SecondFeature(IWebApi webApi)
    {
        this.webApi = webApi;
    }

    public async Task execFeature()
    {
        List<string> classNames = new List<string>();
        var classNameTasks = Enumerable.Range(1, 3).Select(i => webApi.getClassName()).ToArray();
        classNames.AddRange((await Task.WhenAll(classNameTasks)));
        IResult result;
        if (classNames[0] == null)
            result = new TextResult("Error accessing api - check internet connection/api address");
        else 
            result = new TextResult("Hello dear user – we’ve selected three new class names for you, and they are " + classNames[0] + ", " + classNames[1] + ", and " + classNames[2]);
        result.display();
    }
}
公共类第一个功能:IFeature
{
私有IWebApi;
public FirstFeature(IWebApi webApi)
{
this.webApi=webApi;
}
公共异步任务execFeature()
{
string response=wait webApi.getClassName();
i结果结果;
如果(响应==null)
结果=新文本结果(“访问api时出错-检查internet连接/api地址”);
其他的
结果=新文本结果(“您好,亲爱的用户–所选类名为“+响应”);
result.display();
}
}
公共类第二个功能:IFeature
{
私有IWebApi;
公共第二功能(IWebApi webApi)
{
this.webApi=webApi;
}
公共异步任务execFeature()
{
List classNames=新列表();
var classNameTasks=Enumerable.Range(1,3).Select(i=>webApi.getClassName()).ToArray();
AddRange((wait Task.WhenAll(classNameTasks));
i结果结果;
if(类名[0]==null)
结果=新文本结果(“访问api时出错-检查internet连接/api地址”);
其他的
result=newtextResult(“您好,亲爱的用户–我们为您选择了三个新类名,分别为“+classNames[0]+”、“+classNames[1]+”和“+classNames[2]);
result.display();
}
}
如您所见,在这两种实现中,我都要执行
result=newtextResult(“访问api时出错-检查internet连接/api地址”)行以报告错误

OOP/良好设计中的最佳实践是什么,在我的所有实现中都可以访问一个常量
error\u string


现在的情况是,代码是重复的。

我认为没有最佳实践。这只是偏好的问题

我在静态类中存储常量

public static class Constants
{
   public static class Messages
   {
      public const string Error = "Error accessing api...";
      public const string Hello = "Hello ...";
   }
}
用法
仅供参考:一些开发人员更喜欢Enum。

将其放在一个静态类中:

internal static class ErrorMessage
{
    public const string NoAccess = "Error accessing api - check internet connection/api address";
}
您可以通过以下方式引用:

result = new TextResult(ErrorMessage.NoAccess);

或者,您可以使用资源文件。

我通常建议使用资源文件(根据项目设置创建)。如果您想使此代码更易于测试,您可能需要提供某种包装。

除了您的功能显示消息这一事实之外,我认为它不应该这样做,如果您将消息放入代码中,您显然存在本地化问题。无论您将它放在何处以及如何访问它,您都不希望重新编译以获得不同的语言。你甚至不想重新编译来修复一个愚蠢的拼写错误

在代码中,使用错误代码。例如,这可以是枚举。然后在前端应用程序中,提供一个翻译服务(.NET有一个非常好的功能,称为“资源”)

通过这种方式,你可以为不同的前端提供不同的资源(比如法语资源,或者为语言更简单的儿童提供资源,或者为能够处理实际事务的技术人员提供资源)


此外,您还可以拥有一个自动前端,它可以对代码做出反应,而不必解析错误消息,也不必在有人纠正拼写错误或找到更友好的术语时抛出错误。

并非我不同意@Win的答案,我认为,为了避免重复,将逻辑上与IFeature相关的Error和Hello常量放在不相关的静态类中可能不是合适的方法。如果目标是避免重复,那么我希望通过以下方式实现:

public abstract class Feature:IFeature
{
    public static readonly string Error = "Error accessing api...";
    public static readonly string Hello = "Hello ...{0}";

    protected IWebApi webApi;

    protected Feature(IWebApi webApi)
    {
        this.webApi = webApi;
    }
    public async Task execFeature()
    {
        var o = _execFeature();
        IResult result;
        if(o==null)
            result = new TextResult(Error);
        else 
            result = new TextResult( string.Format(Hello, o);
        result.display();
    }
    protected abstract object _execFeature();
}
所以现在我不仅实现了代码重复的最佳最小化,还将错误和Hello放在了逻辑上属于它们的地方。第一个和第二个要素类现在可以从要素类继承:

public class FirstFeature:Feature
{
    public FirstFeature(IWebApi webApi):base(webApi){}

    protected override object _execFeature ()
    {
        //your code for first Feature
        //return response if no error else return null
    }
}

public class SecondFeature:Feature
{
    public SecondFeature(IWebApi webApi):base(webApi){}

    protected override object _execFeature ()
    {
        //your code for second Feature
        //return class name[0] if no error else return null
    }
}

这就是我的设计。

我通常会根据信息的预期受众进行区分。因此,我将它们分为两类
无论类别如何,我都避免多次编写相同的代码(例如消息字符串)

开发者信息

  • 在单元测试中显示的消息、仅在调试过程中显示的消息或记录到超详细诊断文件中的消息
  • 开发者信息不需要本地化,且应使用开发者的语言书写。
    例如,如果开发公司位于莫斯科,那么就有很强的理由用俄语编写开发人员信息
    在实践中,许多开发人员选择英语
  • 实现选项有多种。我通常保持简单,在静态类中使用字段。请注意,对于将显示消息的每种类型,您都可以有一个消息类,或者您可以有一个中心消息类,将多个类分组。您可以有嵌套的消息组。您还可以添加其他类型的常量,以便在代码中使用。。。正如我提到的,选项和偏好比比皆是。

    public static class FeatureMessages
    {
        #region Public Fields
    
        public const string ApiAccessError = 
            @"Error accessing api - check internet connection/api address";
        public const string SelectedClassFormatString = 
            @"Hello dear user – the selected class name is {0}";
    
        #endregion
    }
    
用户消息

  • 向最终用户显示的消息。例如,安装会在用户GUI菜单中的用户警告消息框中提示
  • 这些消息应本地化
  • 实现很简单,至少需要一个默认语言资源文件。有很多资源可以告诉你如何做到这一点,你可以看到一个简单的解释

一个选项是资源文件。特别是当你需要处理本地化时。你是说我应该把它放在一个类中?或者在接口文件中?
internal
用于限制同一程序集(项目)内的使用。因此,如果您将整个内容公开为库/dll,它将不会被访问
public static class FeatureMessages
{
    #region Public Fields

    public const string ApiAccessError = 
        @"Error accessing api - check internet connection/api address";
    public const string SelectedClassFormatString = 
        @"Hello dear user – the selected class name is {0}";

    #endregion
}