C# 难读try..catch..finally块的格式设置?

C# 难读try..catch..finally块的格式设置?,c#,formatting,try-catch-finally,C#,Formatting,Try Catch Finally,如何格式化try..catch.finally块?特别是当只围绕少量代码进行包装时,它会破坏一切,使代码在我看来非常不可读和难看 例如: 这7行代码变成了16行的混乱 有没有关于更好地尝试..捕获..最终格式化的建议?空白。作为最低要求,我总是在每个return语句之前以及代码的“doing stuff”和“creating variables”部分之间加上一行空格 try { MyService service = new Service(); service.DoS

如何格式化try..catch.finally块?特别是当只围绕少量代码进行包装时,它会破坏一切,使代码在我看来非常不可读和难看

例如:

这7行代码变成了16行的混乱


有没有关于更好地尝试..捕获..最终格式化的建议?

空白。作为最低要求,我总是在每个return语句之前以及代码的“doing stuff”和“creating variables”部分之间加上一行空格

try
{
     MyService service = new Service();

     service.DoSomething();

     return something;

 }
catch (Exception ex)
{
     LogSomething();

     return somethingElse;

}
finally
{
     MarkAsComplete();
     service.Dispose();
}

好多了。

嗯,我想那很好。这其中的一部分进入了花括号位置的辩论。您可以这样做:

try {
  //
} catch(Exception ex) {
  //
} finally {
  //
}

不过我更喜欢你的。但是,您可能需要考虑修改代码只有一个返回语句。我发现这是一个更好的设计。

我在同一行用括号格式化代码:

try {
   MyService service = new Service();
   service.DoSomething();
   return something;
} catch (Exception ex) {
   LogSomething();
   return somethingElse;
} finally {
   MarkAsComplete();
   service.Dispose();
}

如果我想要更多的间距,我更喜欢添加空行。这也可以作为代码逻辑块之间的分隔符。

事实上,这对我来说非常好。如果您的实际代码看起来很像这样,那么我真的不会担心它。现在发生的事情很清楚


如果你的实际代码比较复杂,那么考虑把这些块分解成好名字的方法。

我认为你的格式也读得很好。我的建议是尽量少用
catch
语句。只有当你真的需要抓东西的时候才使用它。否则,您可以让程序的其他部分处理异常。整个“早期失败”的概念


就我个人而言,我倾向于在代码中遵循前面的风格。。。它提供了发表评论的空间,并更好地展示了我的逻辑流程

我有一个宽屏,我把它的一边,所以空白允许各种列排列好,不会伤害我太多,因为我有这么多的屏幕房地产,因为它是

try { // getting a service

     MyService service = new Service();
     service.DoSomething();

     return something;

}

catch (Exception ex) { // the fact that a service might be full/timedout

     LogSomething();

     return somethingElse;

} 

finally { // remove any resources the service may still hold.

     MarkAsComplete();
     service.Dispose();

}

你可以考虑容器(非常聪明的工厂)和建议(处理所有混乱的细节)

在代码中,您可能会看到:

//a class that knows how to take care of the messy infrastructure details
public class MyMessyInterceptor : IInterceptor {
    public void Intercept(IInvocation invocation) {
        //handle the messy details of continuing with the method-invocation,
        //but within a try-catch-finally that includes exception handling and
        //call logging.
    }
}

//a function that will configure a container (very smart factory)
public IContainer CreateContainer() {
    var builder = new ContainerBuilder();

    //tell the container-builder about the interceptor
    builder
        .Register(c => new MyMessyInterceptor())
        .Named("keep-my-code-clean")
    ;

    //tell the container what to do when you ask it for a ISomething
    builder
        .Register<SomethingImpl>()
        .As<ISomething>()
        .InterceptedBy("keep-my-code-clean")
    ;

    return builder.BuildContainer();
}

//some function out there in your code somewhere that needs to make a
//service call; there's hundreds of functions out there just like this
//in your code, and they all just got much simpler
public object GottaGoDoSomething() {
    //find the container
    var container = GetTheSingletonContainerObject();
    //ask for an instance of ISomething - it knows to provide a
    //SomethingImpl wrapped in an interceptor that takes care of all
    //the logging and exception handling
    var something = container.resolve<ISomething>();
    //call the big method
    return something.DoSomething();
    //magically (not really), the exception handling and logging are
    //already taken care of
}
//一个知道如何处理混乱的基础结构细节的类
公共类MyMessyInterceptor:IInterceptor{
公共无效拦截(IInvocation调用){
//处理继续方法调用的混乱细节,
//但在一个包含异常处理和
//呼叫记录。
}
}
//配置容器的函数(非常智能的工厂)
公共IContainer CreateContainer(){
var builder=new ContainerBuilder();
//告诉容器生成器有关拦截器的信息
建设者
.Register(c=>newmymessynterceptor())
.Named(“保持我的代码干净”)
;
//告诉容器当你向它要东西时该怎么做
建设者
.Register()
.As()
.InterceptBy(“保持我的代码干净”)
;
返回builder.BuildContainer();
}
//在代码中的某个地方有一些函数需要
//服务呼叫;像这样的函数有数百种
//在你的代码中,它们都变得简单多了
公共对象gottagodoothing(){
//找到容器
var container=GetTheSingletonContainerObject();
//询问ISomething的一个实例-它知道提供一个
//一些被包装在拦截器中的MPL,可以处理所有
//日志记录和异常处理
var something=container.resolve();
//称之为大方法
归还某物;
//神奇的是(不是真的),异常处理和日志记录
//已经照顾好了
}
拦截器类只出现一次。注册每个拦截器和服务类也只发生一次。设置容器(非常智能的工厂)当然很复杂

然而,代码中每一个必须使用服务对象的地方,以及必须将服务对象的使用嵌入复杂而混乱的基础结构细节(如异常处理和日志记录)中的地方,都变得非常干净和简单。只有一个
CreateContainer
,但是有数百个
GottaGoDoSomething
s,所以这非常简单,但代价是有点复杂


(注意:代码示例使用Autofac容器框架和Castle拦截器框架。我知道这是服务位置模式的示例,不是依赖注入模式,但重点是说明拦截器并将其注册到容器中,而不是说明依赖注入。)

I,就像你原来拥有的一样。.cs文件中的物理行不会花费任何费用,也不会更改最终的输出代码。因此,请使用您所需要的一切,以便为您或您的团队提供最佳的可读性

事实上,在编写代码时,您应该尝试使用比这里显示的16行更多的行,为自己或他人添加注释

加入

// a comment that says what's going on

通常,您可以更好地提醒自己这一尝试是什么。当您在6个月后返回时,Catch应该做什么。

您可以使用
using
块而不是显式的
Dispose()
,否则您可能必须在处理它之前检查null,而
using
块可以帮您做到这一点。不幸的是,它确实增加了嵌套=/

try
{
     using(MyService service = new MyService()) 
     {
        service.DoSomething();
        return something;
     }
}
catch (SpecificException ex)
{
     LogSomething(ex);
     return somethingElse;
}
finally
{
     MarkAsComplete();
}

我总是尝试重构我所有的try-catch块,并用它们自己的方法封装它们


这似乎总是让一切都更具可读性,另外,让方法只做一件事是一种很好的编程实践。如果您在try-catch-finally语句的上下都有代码,那么很可能您做的不止一件事。

如果您真的想摆脱强制的格式,但格式很难看(是的,我同意:p)

选择面向方面的编程,你最终会得到一个“尝试” 嵌入
//a class that knows how to take care of the messy infrastructure details
public class MyMessyInterceptor : IInterceptor {
    public void Intercept(IInvocation invocation) {
        //handle the messy details of continuing with the method-invocation,
        //but within a try-catch-finally that includes exception handling and
        //call logging.
    }
}

//a function that will configure a container (very smart factory)
public IContainer CreateContainer() {
    var builder = new ContainerBuilder();

    //tell the container-builder about the interceptor
    builder
        .Register(c => new MyMessyInterceptor())
        .Named("keep-my-code-clean")
    ;

    //tell the container what to do when you ask it for a ISomething
    builder
        .Register<SomethingImpl>()
        .As<ISomething>()
        .InterceptedBy("keep-my-code-clean")
    ;

    return builder.BuildContainer();
}

//some function out there in your code somewhere that needs to make a
//service call; there's hundreds of functions out there just like this
//in your code, and they all just got much simpler
public object GottaGoDoSomething() {
    //find the container
    var container = GetTheSingletonContainerObject();
    //ask for an instance of ISomething - it knows to provide a
    //SomethingImpl wrapped in an interceptor that takes care of all
    //the logging and exception handling
    var something = container.resolve<ISomething>();
    //call the big method
    return something.DoSomething();
    //magically (not really), the exception handling and logging are
    //already taken care of
}
// a comment that says what's going on
try
{
     using(MyService service = new MyService()) 
     {
        service.DoSomething();
        return something;
     }
}
catch (SpecificException ex)
{
     LogSomething(ex);
     return somethingElse;
}
finally
{
     MarkAsComplete();
}