static关键字是什么意思?

Qoo*_*ooe 11 c#

我是C#初学者.我发现有两种方法可以编写代码并输出相同的结果.你能解释一下它们之间的区别吗?何时使用#1和#2?

#1

class Program
{
    static void Main()
    {
        Program min = new Program();
        Console.WriteLine(min.isMin(1, 2));
        Console.ReadLine();
    }

    int isMin(int value1, int value2)
    {
        int Min;
        return Min = Math.Min(value1, value2);
    }
}
Run Code Online (Sandbox Code Playgroud)

#2

class Program2
{
    static void Main()
    {
        Console.WriteLine(isMin(1, 2));
        Console.ReadLine();
    }

    static int isMin(int value1, int value2)
    {
        int Min;
        return Min = Math.Min(value1, value2);
    }
}
Run Code Online (Sandbox Code Playgroud)

Mik*_*scu 14

#1和#2之间的区别在于#1,isMin是类Program的实例成员函数,因此您必须创建Program类的实例

 Program min = new Program()
Run Code Online (Sandbox Code Playgroud)

然后才调用实例成员函数isMin:

 min.isMin(..)
Run Code Online (Sandbox Code Playgroud)


在#2中,isMin是Program类的静态成员函数,由于Main也是同一类的静态成员函数,因此可以从Main函数直接调用isMin.

两者都有效.静态函数Main是程序的"入口点",这意味着它首先被执行.其余的只是面向对象的语义.

编辑

似乎为了更好地说明这一点,一个例子将是有序的.

下面的两个程序除了显示将程序逻辑封装到对象之间的差异以及替代使用静态函数之外,还没有用.

该程序定义了两个操作,并将处理两个数字(示例中为10和25).程序运行时,它会将其操作跟踪到日志文件(每个数字一个).可以想象,这两个操作可以被更严格的算法所取代,并且这两个数字可以被一系列更有用的输入数据所取代.

//The instance-based version:
class Program
{
    private System.IO.StreamWriter _logStream;
    private int _originalNumber;
    private int _currentNumber;

    public Program(int number, string logFilePath)
    {
        _originalNumber = number;
        _currentNumber = number;
        try
        {                
            _logStream = new System.IO.StreamWriter(logFilePath, true);
            _logStream.WriteLine("Starting Program for {0}", _originalNumber);
        }
        catch
        {
            _logStream = null;
        }
    }
    public void Add(int operand)
    {
        if (_logStream != null)
            _logStream.WriteLine("For {0}: Adding {1} to {2}", _originalNumber, operand, _currentNumber);
        _currentNumber += operand;
    }
    public void Subtract(int operand)
    {
        if (_logStream != null)
            _logStream.WriteLine("For {0}: Subtracting {1} from {2}", _originalNumber, operand, _currentNumber);
        _currentNumber -= operand;            
    }
    public void Finish()
    {            
        Console.WriteLine("Program finished. {0} --> {1}", _originalNumber, _currentNumber);
        if (_logStream != null)
        {
            _logStream.WriteLine("Program finished. {0} --> {1}", _originalNumber, _currentNumber);
            _logStream.Close();
            _logStream = null;
        }
    }

    static void Main(string[] args)
    {
        Program p = new Program(10, "log-for-10.txt");
        Program q = new Program(25, "log-for-25.txt");

        p.Add(3);         // p._currentNumber = p._currentNumber + 3;
        p.Subtract(7);    // p._currentNumber = p._currentNumber - 7;
        q.Add(15);        // q._currentNumber = q._currentNumber + 15;
        q.Subtract(20);   // q._currentNumber = q._currentNumber - 20;
        q.Subtract(3);    // q._currentNumber = q._currentNumber - 3;

        p.Finish();       // display original number and final result for p
        q.Finish();       // display original number and final result for q
    }
}
Run Code Online (Sandbox Code Playgroud)

以下是基于静态函数的同一程序的实现.注意我们如何"进行状态"进出每个操作,以及Main函数如何"记住"哪个数据与哪个函数调用有关.

class Program
{
    private static int Add(int number, int operand, int originalNumber, System.IO.StreamWriter logFile)
    {
        if (logFile != null)
            logFile.WriteLine("For {0}: Adding {1} to {2}", originalNumber, operand, number);
        return (number + operand);
    }
    private static int Subtract(int number, int operand, int originalNumber, System.IO.StreamWriter logFile)
    {
        if (logFile != null)
            logFile.WriteLine("For {0}: Subtracting {1} from {2}", originalNumber, operand, number);
        return (number - operand);
    }
    private static void Finish(int number, int originalNumber, System.IO.StreamWriter logFile)
    {
        Console.WriteLine("Program finished. {0} --> {1}", originalNumber, number);
        if (logFile != null)
        {
            logFile.WriteLine("Program finished. {0} --> {1}", originalNumber, number);
            logFile.Close();
            logFile = null;
        }
    }

    static void Main(string[] args)
    {
        int pNumber = 10;
        int pCurrentNumber = 10;
        System.IO.StreamWriter pLogFile;
        int qNumber = 25;
        int qCurrentNumber = 25;
        System.IO.StreamWriter qLogFile;

        pLogFile = new System.IO.StreamWriter("log-for-10.txt", true);
        pLogFile.WriteLine("Starting Program for {0}", pNumber);
        qLogFile = new System.IO.StreamWriter("log-for-25.txt", true);
        qLogFile.WriteLine("Starting Program for {0}", qNumber);

        pCurrentNumber = Program.Add(pCurrentNumber, 3, pNumber, pLogFile);
        pCurrentNumber = Program.Subtract(pCurrentNumber, 7, pNumber, pLogFile);
        qCurrentNumber = Program.Add(qCurrentNumber, 15, qNumber, qLogFile);
        qCurrentNumber = Program.Subtract(qCurrentNumber, 20, qNumber, qLogFile);
        qCurrentNumber = Program.Subtract(qCurrentNumber, 3, qNumber, qLogFile);

        Program.Finish(pCurrentNumber, pNumber, pLogFile);
        Program.Finish(qCurrentNumber, qNumber, qLogFile);
    }
}
Run Code Online (Sandbox Code Playgroud)

另一点需要注意的是,尽管基于第一个实例的示例有效,但在实践中更常见的是将逻辑封装在可以在程序的主入口点中使用的不同类中.这种方法更加灵活,因为它使您可以非常轻松地获取程序逻辑并将其移动到不同的文件,甚至可以移动到甚至可以被多个应用程序使用的不同程序集.这是一种方法.

// Another instance-based approach
class ProgramLogic
{
    private System.IO.StreamWriter _logStream;
    private int _originalNumber;
    private int _currentNumber;

    public ProgramLogic(int number, string logFilePath)
    {
        _originalNumber = number;
        _currentNumber = number;
        try
        {                
            _logStream = new System.IO.StreamWriter(logFilePath, true);
            _logStream.WriteLine("Starting Program for {0}", _originalNumber);
        }
        catch
        {
            _logStream = null;
        }
    }
    public void Add(int operand)
    {
        if (_logStream != null)
            _logStream.WriteLine("For {0}: Adding {1} to {2}", _originalNumber, operand, _currentNumber);
        _currentNumber += operand;
    }
    public void Subtract(int operand)
    {
        if (_logStream != null)
            _logStream.WriteLine("For {0}: Subtracting {1} from {2}", _originalNumber, operand, _currentNumber);
        _currentNumber -= operand;            
    }
    public void Finish()
    {            
        Console.WriteLine("Program finished. {0} --> {1}", _originalNumber, _currentNumber);
        if (_logStream != null)
        {
            _logStream.WriteLine("Program finished. {0} --> {1}", _originalNumber, _currentNumber);
            _logStream.Close();
            _logStream = null;
        }
    }        
}


class Program
{        
    static void Main(string[] args)
    {
        ProgramLogic p = new ProgramLogic(10, "log-for-10.txt");
        ProgramLogic q = new ProgramLogic(25, "log-for-25.txt");

        p.Add(3);         // p._number = p._number + 3;
        p.Subtract(7);    // p._number = p._number - 7;
        q.Add(15);        // q._number = q._number + 15;
        q.Subtract(20);   // q._number = q._number - 20;
        q.Subtract(3);    // q._number = q._number - 3;

        p.Finish();
        q.Finish();     
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 尽早给自己一个忙,并学习何时创建静态方法,何时不要.没有什么比认为他们知道OO编程的开发人员更糟糕了,并且除了静态方法之外什么都没有创建他们的类.它让我起了墙! (4认同)

Col*_*itz 5

这里的关键区别是基于面向对象的编程.C#是一种面向对象的语言,其中的大部分内容都是对象.在这种情况下,程序是一个对象.它很特殊,因为它具有静态void Main()函数,即程序的"入口点".

差异是因为isMin函数上的静态修饰符.类定义对象的工作方式.实际创建一个时,就像使用新的Program()一样,你已经'实例化',或者制作了该对象的实际工作副本.

通常这样做是为了跟踪作为该对象一部分的一组变量,但在这种情况下,没有这样的变量.

在第一种情况下,您正在创建对象程序的实例,并告诉它在该实例上执行其"isMin"函数.在第二种情况下,您没有创建任何实例,并且您告诉它执行与该类关联的"isMin"函数(而不是该对象的实例).除了一些更简单的语法之外,这里没有真正的区别,因为在对象中没有跟踪数据.

当您拥有对象数据时,您会发现这很重要,因为当您处于静态函数时,您将无法访问"实例"数据.要了解更多信息,请研究面向对象的编程.