【问题标题】:What is the use of static methods in C#? Please explain with examples [closed]C#中的静态方法有什么用?请举例说明[关闭]
【发布时间】:2022-01-04 01:08:06
【问题描述】:

我不明白 C# 中静态方法的用法。我应该在哪些情况下使用它们?

请提供代码示例和解释。

【问题讨论】:

  • 静态函数和变量具有类范围的作用域,而非静态成员与单个实例相关联。考虑一种情况,您想要计算已创建的类的实例。您将创建一个静态 int,初始化为零。在每个类构造函数中,您将其加一。然后你会提供一个静态方法或属性来读取值
  • 静态函数有什么用,你什么时候使用这些?您对它们的用法有何理解?在理解静态函数之前先理解实例函数有点奇怪

标签: c# oop static


【解决方案1】:

我将从一些术语开始。有 instance 方法和 static 方法。实例方法属于类或类型的实例。静态方法属于类型,不属于任何特定实例。

例如,如果没有 List<int> 的实例,您就无法添加到 List<int>

var list = new List<int>(); // creates an instance
list.Add(1);

当您调用Add 时,您将添加到List&lt;int&gt; 的特定实例。您可以有多个实例并为每个实例添加不同的编号。它是一个实例方法。

有时实例是不必要的。这方面的一个例子是静态Math 类,它具有各种静态方法,如Sqrt 来获取数字的平方根。

var squareRoot = Math.Sqrt(100);

将此与更改列表的List&lt;T&gt;s Add 方法及其Count 属性进行比较,该属性因每个实例而异,因为每个列表可以有不同数量的项目。

Sqrt 不会改变任何东西,也不依赖于类的状态。您可以将Math 设为非静态并将Sqrt 设为实例方法,但有什么意义呢?然后你必须编写这段代码:

var math = new Math();
var squareRoot = math.Sqrt(100);

...但是即使您创建了多个Math 实例,结果也总是相同的,那么拥有Math 实例的意义何在?

不依赖于实例状态或不改变实例状态的方法是静态方法的良好候选者。

这不是静态方法的唯一用途,但它是一种常见的用途。如果您不需要类的实例来使方法工作,那么该方法可以是静态的。


静态成员也可以改变类的静态状态,如下例所示:

public class Counter
{
    private static int _count;

    public static void Increment()
    {
        _count++;
    }

    public static int Count => _count;
}

没有Counter 的实例。只有类型,当您调用 Counter.Increment() 时,您会更改检查 Count 属性的任何代码的 _count 的值。

我们可以编写像这样修改其状态的静态类,但也有缺点。如果我们决定出于某种原因我们想要计算两个不同的东西,我们不能使用上面的类。如果我们可以创建单独的 Counter 实例,那么我们可以单独递增它们,就像将不同的项目添加到 List&lt;T&gt; 的不同实例一样。

像这样的静态方法也引入了全局状态。这意味着整个应用程序中的任何代码都可能调用方法并更改某些静态状态,这可能会使代码更难理解。

全局状态不会自动出错。出于某种原因,它可能正是您想要的。但我们倾向于避免使用它,因为通过更改和读取相同的值,更难分辨代码的不同部分如何相互影响。


这个问题无疑还有更多答案,但这应该涵盖静态方法的更常见用途。

【讨论】:

    【解决方案2】:

    我相信更多知识渊博的人会给出更好的答案,但无论如何这里有一个。我想这里static关键字被理解了,不会讨论静态属性或字段,只讨论静态方法。

    当面向对象编程 (OOP) 非常流行时,C# 就诞生了。所以它被设计成(几乎)所有东西都是一个对象。这大致意味着您不能真正定义超出类范围的函数。顺便说一句,类中定义的“函数”称为方法。

    如您所知,一个类(在一般意义上)应该将相关的数据和函数关联在一起。但有时,您可能没有任何有意义的数据与一个函数或一组函数相关联。您可能只对函数(或一组函数)感兴趣。

    在这种情况下,您不需要实例,因为实例的目的是存储您不感兴趣的状态。因此,解决方案是通过使用静态类来摆脱实例包含静态方法。

    通过这种方式,您可以更接近旧的编程范式:过程式编程,它早于 OOP。

    C# Programming Guide给出的经典例子

    静态类可以作为一个方便的容器来存放 只对输入参数进行操作而不必获取的方法 或设置任何内部实例字段。例如,在 .NET 类中 库,静态 System.Math 类包含执行的方法 数学运算,无需存储或检索 对 Math 类的特定实例唯一的数据。那 就是,你通过指定类名来应用类的成员 和方法名[...]。

    这里是使用三个静态方法的例子,AbsFloorRound,定义在静态类Math中:

    var number = -5.263;  
    var absoluteValue = Math.Abs(number);  // 5.263
    var floorNumber = Math.Floor(number);  // -6
    var roundedNumber = Math.Round(Math.Abs(number)); // 5
    

    C#是一种多范式语言,除了面向对象编程外,还部分支持函数式编程(FP)。在 FP 中,函数是代码的基本构建块。他们没有与之相关的数据。它们可以接受输入(参数)并且可以产生输出(返回值)。它们不应该有副作用(这称为纯度)。为了帮助支持这些原则,C# 中添加了许多功能。其中之一,扩展方法,基于静态方法。

    这是一个具体的例子:受函数式编程启发的 C# 中最明显的部分是 Linq。如果没有静态扩展方法,Linq 就无法存在。

    请参阅the C# Programming Guide 了解扩展方法。

    扩展方法使您能够将方法“添加”到现有类型 无需创建新的派生类型、重新编译或以其他方式 修改原始类型。扩展方法是静态方法,但是 它们被称为扩展类型的实例方法。 对于用 C#、F# 和 Visual Basic 编写的客户端代码,没有 调用扩展方法和调用扩展方法之间的明显区别 类型中定义的方法。最常见的扩展方法是 LINQ 标准查询运算符,将查询功能添加到 现有的 System.Collections.IEnumerable 和 System.Collections.Generic.IEnumerable 类型。

    这是一个 Linq 示例:

    var bestMovies = movies
        .Where(m => m.Rating > 8)
        .OrderByDescending(m => m.Rating);
    

    这里WhereOrderByDescending 是静态方法。

    所以静态方法是 C# 的一个非常重要的组件,并且被大量使用。

    当您只需要一个不依赖关联数据的简单辅助方法时,可以使用静态方法。它们允许简单的构造,可以快速轻松地帮助处理冗余代码。它们是在适当情况下使用的宝贵工具。

    这是一对静态方法的示例(一个是扩展方法)。您可以在 Linqpad 中运行它。

    void Main()
    {
        var hello = "Hello";
        Console.WriteLine(hello.Decorate("@")); // ====== @HELLO ======
        
        var result = Utils.MyMathFunction(6); 
        Console.WriteLine(result); // 42
    }
    
    // You can define other methods, fields, classes and namespaces here
    public static class Utils
    {
        public static string Decorate(this string text, string decoration)
        {
            return $"====== {decoration}{text.Trim().ToUpper()} ======";
        }
        
        public static double MyMathFunction(double number)
        {
            return (number + 3) * number - 12;
        }
    }
    

    【讨论】:

    • 关于 Linq 方法:这些方法略有不同,因为它们是 扩展方法 - 技术上是静态方法,但使用起来类似于在类外部定义的实例方法。
    • 您的意思是“扩展方法使您能够向现有类型“添加”方法,而无需创建新的派生类型、重新编译或以其他方式修改原始类型。扩展方法是静态方法,但它们是就好像它们是扩展类型的实例方法一样调用。” ?上面已经说明了。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-03-14
    • 1970-01-01
    • 1970-01-01
    • 2019-05-25
    相关资源
    最近更新 更多