Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/260.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何决定C#静态和非静态方法?_C#_Oop_Class Design - Fatal编程技术网

如何决定C#静态和非静态方法?

如何决定C#静态和非静态方法?,c#,oop,class-design,C#,Oop,Class Design,[编辑] 我最初的问题是“为什么要在静态和非静态之间做出决定?两者都是一样的…” 不幸的是,它被编辑成了一个特定于C的问题,这是我真正想要避免的 因此,让我做一些补充: 当我说接口时,我不是指C#-关键字接口,而是指我所理解的类似于C++接口的东西:一组定义良好的函数来操作我的对象。 当我说削弱我的界面时,我的意思是我有不同的函数(静态/非静态)做同样的事情。当有不同的函数来做同一件事时,我的接口就不再是很好的定义了 因此,正如看门人鲍勃所说,我可以实现一个Validate()函数 而且 myC

[编辑]

我最初的问题是“为什么要在静态和非静态之间做出决定?两者都是一样的…”

不幸的是,它被编辑成了一个特定于C的问题,这是我真正想要避免的

因此,让我做一些补充:

当我说接口时,我不是指C#-关键字接口,而是指我所理解的类似于C++接口的东西:一组定义良好的函数来操作我的对象。 当我说削弱我的界面时,我的意思是我有不同的函数(静态/非静态)做同样的事情。当有不同的函数来做同一件事时,我的接口就不再是很好的定义了

因此,正如看门人鲍勃所说,我可以实现一个Validate()函数

而且

myConcreteDocumentObject.Validate();
Document.Copy(myConcreteDocumentObject, toPath)
要回到my Copy()-示例,可以实现Copy(),如下所示

而且

myConcreteDocumentObject.Validate();
Document.Copy(myConcreteDocumentObject, toPath)

当我想到一个包含属于我的文档的所有文件的文件夹时(在本例中,我并不依赖于具体的实例,而是依赖于其他东西:)

一般来说,我说的是静态方法,而不是静态类(对不起,如果我忘了标注)

但正如Anton Gogolev所说,我认为我的Document类不是一个好例子,设计得也不好,因此我认为我必须看看单一责任原则

我还可以实现某种与DocumentClass一起运行的ManagerClass:

例如:

myDocumentManagerObject.Copy(myConcreteDocumentObject, toPath);

但如果我提到方法1),我倾向于创建自己执行任务的对象,而不是使用我的DocumentObject执行任务的其他对象(DocumentManager)

(我希望这不会导致关于OOP的宗教讨论;))

[/编辑]


旧版本: 起初,这似乎是一个非常基本的问题,比如“何时使用静态方法,何时不使用”,但这是我时不时遇到的问题(我很难描述真正的问题是什么;也许这只是为了得到为什么(不)使用1)或为什么(不)使用2)的原因)

(虽然我使用的是C#语法,但这不是C#限制的问题)

在OOP中,有两种处理对象的方法:

1) 如果我想让我的目标做点什么,我只要告诉他:

myConcreteObject.DoSomething();
就像和一个物体说话一样

2) 或者,如果您喜欢静态方法:

ObjectClass.JustDoIt();
在某种程度上,我认为静态函数“感觉”更好。所以我倾向于经常使用静态方法(独立于具体实例-独立性总是一件好事)

因此,在设计课程时,我通常必须决定是采用方法1)还是方法2):

假设您有一个类“Document”,它代表应保存到数据库中的文档:

文件

  • 由文件系统中的一个或多个图像文件组成(这些文件成为单个文档页)
  • 有一个类似于参考书目的字段,用户可以向其中添加有关文档的信息,并将其保存到一个额外的文件中
  • 并且应该有一些操作,如Copy()、AddPage()、RemovePage()等
现在我要面对几种创建此类的方法:

//----- 1) non static approach/talking to objects -----
Document newDocument = new Document();

// Copy document to x (another database, for example)
newDocument.Copy(toPath);
我喜欢这样:我告诉文档将其自身复制到数据库x,而对象本身就这样做了。很好

//----- 2) static approach ----------------------------
Document.Copy(myDocumentObject, toPath);
为什么不呢?也不错,感觉很方便

那么,实施哪一个呢?二者都或者将静态方法放在一种助手类中?或者选择方法1)并坚持使用它,以不削弱文档类的接口

在考虑这两种方法时,我得出的结论是(理论上)可以将任何函数作为静态函数来实现:

Class.Function(aConcreteClassObject, parameters);
但也是非静态的:

aConcreteObject.DoSomething(parameters);
举一个真实的例子:

[编辑(从路径“对不起,我忘了”中添加参数]]

[/编辑]

而且:

//----- 1) non static approach ------------------------
ExampeFileClass fileObject = new ExampleFileClass();
fileObject.Copy(toPath);
甚至(有点OOP过头了):

那么,为什么(不)使用1)或为什么(不)使用2)


(我不会过多地关注文档类示例,因为它更像是一个关于良好类设计的一般性问题。)

KISS。如果你不需要调用构造函数,那就更好了

另外,一个静态的方法应该告诉您函数是如何运行的:

  • 它不会对传递给它的变量之外的变量进行操作
  • 除了调用方法外,它不需要任何内存(不计算函数返回的内容)
还有一些重要的事情需要注意:

  • 某些实例(Java)中的静态方法不能被重写/子类化,因此它们更适合于实现不需要更改的情况
  • 有些人认为静态方法是可行的
我还想提到这一点,坦率地说,这一点提供了关于这个主题的大量讨论。

我的“规则”是:

  • 如果我不需要使用类中的属性,请将其设置为静态。(换言之,如果方法没有真正附加到类,就在那里进行逻辑关联,使用static)

通常,如果您有以下方法:

Document.Copy(myDocumentObject, toPath);

我认为最好使用非静态方法,因为第一个参数是文档,这表明它实际上是对文档的操作。

一般来说,对于对象而言,“复制”自己通常意味着将数据克隆到新对象中。这里描述的“复制”是文件系统代表您执行的操作,而不是对象。因此,我将使其成为一个静态方法,而不是文档实例上的方法。

与altCongnito相同,我将添加该fileObject。复制每个人都将使用,而不是对象fileObject。 对于与类有理想关系的函数,而不是它的函数依赖关系的函数,它是静态的。

现在开始

首先:

所以我倾向于经常使用静态方法(独立于具体实例-独立性总是好的)
//----- 2) static approach ----------------------------
File.Copy(fromPath, toPath);    // .Net-Framework-like
//----- 1) non static approach ------------------------
ExampeFileClass fileObject = new ExampleFileClass();
fileObject.Copy(toPath);
//----- 1) non static approach, too -------------------
fileObject.ToPath = @"C:\Test\file.txt";     // property of fileObject
fileObject.Copy();                           // copy to toPath
Document.Copy(myDocumentObject, toPath);
interface IDocument 
{
   void Print(IDevice targetDevice);
}

IDocument instance;

instance = new PdfDocument();
instance.Print(printer);

instance = new WordDocument();
instance.Print(printer);
public static errors Validate(Document myDoc)
{
..some validation code
}
public static errors ValidateAndSave(Document myDoc)
{
    errors docErrors = Validate(myDoc);
    if(docErrors.count==0)
    {
         docErrors = SaveToDB(myDoc);
    }

   return docErrors; 
} 
document1.copy(toPath)
Document.copy(fromPath, toPath)