C# 私有静态与私有方法困境

C# 私有静态与私有方法困境,c#,C#,你好,哲学问题 有一个私有静态方法无法访问实例字段,就我的阅读资料而言,这些方法提供了一点性能改进 将方法标记为静态后,编译器将发出 这些成员的非虚拟呼叫站点。发出非虚拟呼叫 站点将阻止在运行时对每个调用进行检查,以确保 当前对象指针为非空。这可能会导致 性能敏感代码的可测量性能增益。在某些方面 在某些情况下,无法访问当前对象实例表示 正确性问题 FxCop 那么,当我们可以在私有静态方法参数中放置实例字段时,为什么要使用普通私有方法呢?这不是效率低下吗 想象一下我的意思: public cla

你好,哲学问题

有一个私有静态方法无法访问实例字段,就我的阅读资料而言,这些方法提供了一点性能改进

将方法标记为静态后,编译器将发出 这些成员的非虚拟呼叫站点。发出非虚拟呼叫 站点将阻止在运行时对每个调用进行检查,以确保 当前对象指针为非空。这可能会导致 性能敏感代码的可测量性能增益。在某些方面 在某些情况下,无法访问当前对象实例表示 正确性问题

FxCop

那么,当我们可以在私有静态方法参数中放置实例字段时,为什么要使用普通私有方法呢?这不是效率低下吗

想象一下我的意思:

public class A
{
    private readonly string _key = "ssss";

    public bool IsGoodKey()
    {
    }

    private static bool ValidateKeyStatic(string key)
    {
        return string.IsNullOrEmpty(key);
    }
    private bool ValidateKey()
    {
        return string.IsNullOrEmpty(_key);
    }
}
现在有两种方法可以实现IsGoodKey:


为什么不总是使用私有静态呢?

如果性能是静态的全部目的,那么当然可以将任何东西都设置为静态。但实际上,关键字不是关于性能,而是关于语义——也就是说,成员属于类,因此属于所有实例,还是属于类的特定实例

假设您创建了多个类实例。如果每个实例都有一个_键,那么您肯定需要一个实例字段,而不是静态字段。另一方面,如果所有实例共享同一个键,当然可以将其设置为静态


毕竟,性能只是关键字的副作用,您永远不应该纯粹基于性能考虑来做出设计决策。

如果性能是静态的全部目的,那么您当然可以使任何东西都是静态的。但实际上,关键字不是关于性能,而是关于语义——也就是说,成员属于类,因此属于所有实例,还是属于类的特定实例

假设您创建了多个类实例。如果每个实例都有一个_键,那么您肯定需要一个实例字段,而不是静态字段。另一方面,如果所有实例共享同一个键,当然可以将其设置为静态

毕竟,性能只是关键字的一个副作用,您永远不应该在纯粹考虑性能的情况下做出设计决策

将方法标记为静态后,编译器将向这些成员发出非虚拟调用站点。发出非虚拟调用站点将阻止在运行时对每个调用进行检查,以确保当前对象指针非空。这可以为性能敏感的代码带来可测量的性能增益。在某些情况下,无法访问当前对象实例表示存在正确性问题

我可能错了,但我认为您混淆了当前对象指针是非空检查和静态调用ValidateKeyStatic_键中传递到静态方法_键的参数检查

第一个是指调用方法的指针。对非静态方法编写以下调用时:

福芭芭拉

将为foo插入一个自动的非null运行时检查,如果它恰好为null,您将得到臭名昭著的ReferenceNullException,并且您的程序将崩溃。如果该方法是静态的,则可以避免此检查,从而提高性能,因为该方法不会在对象的任何特定实例上调用

它与你在方法栏上执行什么样的检查无关

将方法标记为静态后,编译器将向这些成员发出非虚拟调用站点。发出非虚拟调用站点将阻止在运行时对每个调用进行检查,以确保当前对象指针非空。这可以为性能敏感的代码带来可测量的性能增益。在某些情况下,无法访问当前对象实例表示存在正确性问题

我可能错了,但我认为您混淆了当前对象指针是非空检查和静态调用ValidateKeyStatic_键中传递到静态方法_键的参数检查

第一个是指调用方法的指针。对非静态方法编写以下调用时:

福芭芭拉

将为foo插入一个自动的非null运行时检查,如果它恰好为null,您将得到臭名昭著的ReferenceNullException,并且您的程序将崩溃。如果该方法是静态的,则可以避免此检查,从而提高性能,因为该方法不会在对象的任何特定实例上调用


它与您在方法栏中对blah insisde执行的检查与否无关。

任何更改状态的操作都必须是公共的,并且不会采用与参数相同的类型。通常我们使用类中的helper方法作为私有静态或公共静态,以便获取新对象或
通过一些操作,我不需要在不知道其依赖关系的情况下重新创建整个对象。希望这能澄清你的问题。@Saravanan:你为改变你的状态所做的任何操作都必须是公开的,这根本不是真的。同样地,并且不会采用与参数相同的类型-嗯,可能是这样。例如,您可以有一个方法将属性从一个对象复制到另一个对象。@JonSkeet,您是对的,我想说的是,它应该是非静态的,但被称为public。任何更改状态的操作都必须是public的,并且不会采用与参数相同的类型。通常我们使用类中的helper方法作为私有静态或公共静态,因此为了获得一个新对象或获得一些操作,我不需要在不知道其依赖关系的情况下更新整个对象。希望这能澄清你的问题。@Saravanan:你为改变你的状态所做的任何操作都必须是公开的,这根本不是真的。同样地,并且不会采用与参数相同的类型-嗯,可能是这样。例如,您可以有一个方法将属性从一个对象复制到另一个对象。@JonSkeet,您是对的,我想说的是它应该是非静态的,但被称为public为什么调用不是虚拟的?ValidateKey是一个虚拟调用,该方法是否为虚拟并不重要。发出的IL仍然是一个callvirt,当调用该方法时,编译器将始终必须对此执行非空检查。您所说的完全正确,但我觉得我的问题仍然没有得到回答。静态方法的行为封装在类中。假设_key在其他实例中具有不同的值。为什么不使用带有合适参数的“静态”方法来用该方法得出结论呢。OOP仍然不会得到验证,只需添加一个字的static,代码就会更加高效。我能理解这里的一个担忧。私有静态不应更改类状态。但在其他情况下,我看不到drawbacks@Pawel好吧,如果每个方法都是静态的,那么您就完全失去了OOP的任何好处,即多态性。如何重写基类中的任何方法?你将如何实现任何接口?@HimBromBeere-Yeap,我不是在谈论公共方法。这里只有列兵:@Pawel好的,我明白你的意思。所以不用myInstance.DoSomething,而是使用DoSomethingmyInstance,对吗?嗯,我想性能优势对于大多数场景来说是可以忽略的,而我上面提到的实际语义更重要。为什么调用不是虚拟的?ValidateKey是一个虚拟调用,该方法是否为虚拟并不重要。发出的IL仍然是一个callvirt,当调用该方法时,编译器将始终必须对此执行非空检查。您所说的完全正确,但我觉得我的问题仍然没有得到回答。静态方法的行为封装在类中。假设_key在其他实例中具有不同的值。为什么不使用带有合适参数的“静态”方法来用该方法得出结论呢。OOP仍然不会得到验证,只需添加一个字的static,代码就会更加高效。我能理解这里的一个担忧。私有静态不应更改类状态。但在其他情况下,我看不到drawbacks@Pawel好吧,如果每个方法都是静态的,那么您就完全失去了OOP的任何好处,即多态性。如何重写基类中的任何方法?你将如何实现任何接口?@HimBromBeere-Yeap,我不是在谈论公共方法。这里只有列兵:@Pawel好的,我明白你的意思。所以不用myInstance.DoSomething,而是使用DoSomethingmyInstance,对吗?嗯,我想性能优势对于大多数场景来说是可以忽略的,而我上面提到的实际语义更重要。
    public bool IsGoodKey()
    {
        return ValidateKeyStatic(_key);
    }
    public bool IsGoodKey()
    {
        return ValidateKey();
    }