关于 C#“使用”的风格/可读性问题陈述

发布于 2024-09-02 12:00:02 字数 1133 浏览 1 评论 0 原文

我想知道您对我持观望态度的编码风格问题的看法。我意识到可能没有明确的答案,但我想看看是否对一个方向或另一个方向有强烈的偏好。

我正在研究一个在很多地方添加 using 语句的解决方案。我经常会遇到这样的情况:

{
    log = new log();
    log.SomeProperty = something;  // several of these
    log.Connection = new OracleConnection("...");
    log.InsertData(); // this is where log.Connection will be used
    ... // do other stuff with log, but connection won't be used again
}

其中 log.Connection 是一个 OracleConnection,它实现了 IDisposable。

我内心的整洁主义者想将其更改为:

{
    using (OracleConnection connection = new OracleConnection("..."))
    {
        log = new log();
        log.SomeProperty = something;
        log.Connection = conn;
        log.InsertData();
        ...
    }
}

但是热爱简洁和稍微更快地完成工作的人想要这样做:

{
    log = new log();
    log.SomeProperty = something; 
    using (log.Connection = new OracleConnection("..."))
        log.InsertData();
    ...
}

出于某种原因,我觉得这样做有点肮脏。你觉得这样不好吗?如果您认为这不好,为什么?如果好的话,为什么?

编辑:请注意,这只是众多示例中的一个(有些人为的)。请不要关注这样一个事实:这恰好表明记录器类的接口考虑不周。这与我的问题无关,而且我也无权改进课程本身。

I'd like to know your opinion on a matter of coding style that I'm on the fence about. I realize there probably isn't a definitive answer, but I'd like to see if there is a strong preference in one direction or the other.

I'm going through a solution adding using statements in quite a few places. Often I will come across something like so:

{
    log = new log();
    log.SomeProperty = something;  // several of these
    log.Connection = new OracleConnection("...");
    log.InsertData(); // this is where log.Connection will be used
    ... // do other stuff with log, but connection won't be used again
}

where log.Connection is an OracleConnection, which implements IDisposable.

The neatnik in me wants to change it to:

{
    using (OracleConnection connection = new OracleConnection("..."))
    {
        log = new log();
        log.SomeProperty = something;
        log.Connection = conn;
        log.InsertData();
        ...
    }
}

But the lover of brevity and getting-the-job-done-slightly-faster wants to do:

{
    log = new log();
    log.SomeProperty = something; 
    using (log.Connection = new OracleConnection("..."))
        log.InsertData();
    ...
}

For some reason I feel a bit dirty doing this. Do you consider this bad or not? If you think this is bad, why? If it's good, why?

EDIT: Please note that this is just one (somewhat contrived) example of many. Please don't fixate on the fact that this happens to indicate a logger class with a poorly thought-out interface. This is not relevant to my question, and I'm not at liberty to improve the classes themselves anyway.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

悲欢浪云 2024-09-09 12:00:02

他们都很可怕。两者都不做。

您正在制作我所说的“高维护等级”在这里。高维护班有一份合同,上面写着“我要求你给我一堆资源,你需要知道我什么时候用完它们并适当地清理它们”。这个契约意味着类的用户必须知道类是如何实现的,从而违反了最初创建类的封装和抽象原则。

您可以通过评论来判断这一点:这是使用连接的地方,我知道不会再次使用该连接。你怎么知道的?您只知道这是否是该类的记录在案的合同。这对于强加给一个类的消费者来说并不是一个好的契约。

一些改进的方法:

1)使记录器成为一次性的。完成后让它清理连接。这样做的缺点是记录器保持连接的时间超过了必要的时间。

2)使InsertData将连接作为参数。调用者仍然可以负责清理连接,因为记录器不会保留它。

3)创建第三个类“Inserter”,它是一次性的,并在其构造函数中接受日志和连接。插入器在废弃连接时将其废弃;然后调用者负责处理插入器。

They are both horrid. Do neither of them.

You're making what I call a "high maintenance class" here. The high maintenance class has a contract that says "I require you to give me a bunch of resources, and you're required to know when I'm done with them and clean them up appropriately". This contract means that the user of the class has to know how the class is implemented, thereby violating the principle of encapsulation and abstraction that motivated making a class in the first place.

You can tell this by your comment: this is where the connection is used, I know the connection will not be used again. How do you know that? You only know that if that is the documented contract of the class. That's not a good contract to impose upon the consumer of a class.

Some ways to make this better:

1) make the logger disposable. Have it clean up the connection when it is done. The down side of this is that the logger holds on to the connection for longer than necessary.

2) make InsertData take the connection as a parameter. The caller can still be responsible for cleaning up the connection because the logger does not hold onto it.

3) make a third class "Inserter" which is disposable and takes a log and a connection in its constructor. The inserter disposes of the connection when it is disposed; the caller then is responsible for disposing the inserter.

一花一树开 2024-09-09 12:00:02

我同意理想情况下 log 本身应该实现 IDisposable,但我们假设这是不可能的,并解决 OP 实际提出的问题。

第二种方法更好,因为它可以用更少的代码来完成同样的事情。在这里引入额外的connection变量没有任何好处。

另请注意,您可以在 using 块之外进行其他初始化。这在这里并不重要,但如果您“使用”一些非常昂贵的资源,则可能很重要。那是:

log = new log();
log.SomeProperty = something; // This can be outside the "using"
using (OracleConnection connection = new OracleConnection("..."))
{
    log.Connection = conn;
    log.InsertData();
    ...
}

I agree that ideally log itself should implement IDisposable, but let's assume that's not possible and address the question the OP actually asked.

The second way is better, simply because it's less code that accomplishes the same thing. There is no advantage to introducing an additional connection variable here.

Also note that you could do other initialisation outside of the using block. It won't matter here, but may matter if you're "using" some really expensive resource. That is:

log = new log();
log.SomeProperty = something; // This can be outside the "using"
using (OracleConnection connection = new OracleConnection("..."))
{
    log.Connection = conn;
    log.InsertData();
    ...
}
倦话 2024-09-09 12:00:02

我会倾听你内心的整洁。我个人更喜欢他的方式。

I would listen to the neatnik in you. I like his way better personally.

埋情葬爱 2024-09-09 12:00:02

两种使用using的方式是完全等价的。无论哪种方式,您最终都会得到一个仍在范围内但具有已释放连接的日志。更好的方法是使日志成为一次性日志,并让其 dispose 方法处理其连接,将日志放入 using 语句中,而不是连接本身。

The two ways of using using are totally equivalent. Either way, you end up with a log that's still in scope but has a disposed connection. It's way better to make the log disposable and have its dispose method dispose of its connection, putting the log in the using statement, not the connection itself.

烟凡古楼 2024-09-09 12:00:02

如果 log 实现 IDisposable,则执行第二个选择,因为大括号是显式的。在某些情况下,您可以使用多个 using 语句:

using (Graphics g = ...)
using (Pen p = new Pen ...)
using (Font f = new Font ...)
{



}

您可以只使用一组大括号。这可以避免疯狂的缩进。

If log implements IDisposable, then do the second choice, as the braces are explicit. In some cases you can use multiple using statements:

using (Graphics g = ...)
using (Pen p = new Pen ...)
using (Font f = new Font ...)
{



}

where you can get away with only using 1 set of braces. This avoids crazy indents.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文