可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I just want to understand the purpose that static method serves and what are the desirable situation where i can create static methods except some would say that static methods are used for creating helper.
Consider i have 1 website that will be used in my company only like Human resource management system like websites.
Now after Admin login in to the system admin will see the list of employees.so the method is simple which does nothing more than fetching all details of employees from employee table and will display them on the web site and this method will be define in business access layer like this in .net:
public class EmployeeBal
{
public List<Employee> GetAllEmployees()
{
return Select * from Employee
}
}
This is how i would call this method from my application.For Eg(.aspx page or mvc controller etc....)
var employeeBal= new EmployeeBal();
employeeBal.GetAllEmployees();
So my question is should i create this method as static method or non static method??
Note:This is just an example of method and this method is in my business access layer.
Consider i have 1 ecommerce website where on the home page i am displaying some list of products and on visit of that website every users can see that list of products.
so my function would be same as above define in Business acess layer:
public class ProductBal
{
public List<Product> DisplayProductonHomePage()
{
return Select * from Products
}
}
So my question would be same like whether to create this method as static method or non-static method and what will happen if more than 10 users at same time simultaneously access this website then what will be the behaviour/implications of this method???
Will this method will serve the purpose of this each user if we declare this method as static??
Can anybody answer this question with briefly explaining every scenario???
回答1:
A static method makes sense when there’s no state to maintain. What do I mean by state? Well, consider the following: You have two distinct objects, a
and b
, which are both of type EmployeeBal
. Is there ever a case in your program where a.GetAllEmployees()
and b.GetAllEmployees()
would yield different results?
If not, then why do the objects a
and b
exist at all? The whole point of having objects is to associate some distinct state with them. If two different objects can never refer to a different state, then they fulfil no purpose.
In fact, in this situation your EmployeeBal
would be exactly equivalent to System.Math
, and all its methods are “helper methods” (if that’s what you want to call them). In this case, forget about static methods for a minute: your whole class should be static (static class EmployeeBal
), and it should not have any constructors; because the concept of an object of type EmployeeBal
simply makes no sense. In fact, in other languages EmployeeBal
wouldn’t be a class at all; instead, it would be something generally called a module: a unit that logically groups code. C# has no modules, and all code must reside within classes. Classes thus fulfil a dual purpose: they group code, and they generate objects.1
Now consider a less extreme case: EmployeeBal
objects actually maintain state, and differ. Yet GetAllEmployees()
will still yield the same result, regardless of which object calls the method.
In this case, EmployeeBal
obviously cannot be a static class. But GetAllEmployees
is still stateless, and thus doesn’t belong to objects of type EmployeeBal
. And thus the method should be static.
1 This lack of distinction between two fundamentally distinct concepts (module and class) is actually quite annoying, and the main reason that C# behaves this way is because it was conceived to be similar to Java. It was a mistake in hindsight, but not a serious one.
回答2:
Is there a reason why the method should be static? If not I'd always side with non-static.
One big reason is being able to write unit tests.
In order to write unit tests you want to be able to isolate the class you're testing from other classes. But if class A contains a reference to static class B, then you can't test A without testing B. Maybe B depends on connection strings or config settings. Maybe B depends on other static classes. Now you can't test A unless B and everything it depends on are in place.
If, on the other hand, class A depends on an interface like IEmployeeProvider
that gets provided through its constructor then you can test class A with a mocked implementation of IEmployeeProvider
.
If A has IEmployeeProvider
as an argument in its constructor then you can tell by looking at the constructor that it depends on IEmployeeProvider
. But if it depends on a static EmployeeProvider
class somewhere inside a method then the dependency is hidden. You have to read the whole class to know what it depends on.
Also, the static class itself can be harder to test. Unless it's absolutely always going to remain stateless then it's better to have a non-static class that you can unit test.
回答3:
It's fine to have multiple threads executing the same static method, as long as the method does not access static state such as field or properties. In that case, the shared objects stored in the fields/properties must themselves be thread safe. The data access parts of .Net are not designed to be thread safe.
As soon as you start considering aspects such as managing a database connection that can be reused for several queries during the execution of a single web request, you should consider if static is the best approach. Since you cannot store the connection in a static field as explained above, you will have to pass it as a parameter to each static method. On the other hand, if you pass the connection to a constructor and store it in a (non-static) field, you can access it from multiple non-static methods of that instance, which will IMO be easier to manage.
This is quite a big topic however, and in general the management of class dependencies is quite tricky to get right in OOP. Some programmers prefer to delegate this task to an "Inversion of Control"-library. There are many available for .Net such as Microsoft Unity, StructureMap, AutoFac, etc.
回答4:
To answer your question:
So my question is should i create this method as static method or non static method??
Note:This is just an example of method and this method is in my business access layer.
I would make those methods static - given what you provided. But I bet that you would have instance variables either declared in your class, or in methods in that class, which then of course that would mean don't make it static.
So a determining factor for me if I decide to use a static method or not has to do with re-use and resources.
If I find myself re-using a method many times over, and I conclude it doesn't need state (kept in memory) - I will make it a static method.
Also I usually will make my methods static if they can be used in other applications or if I think they will be useful down the road.
For example I recently wrote a method that converts a excel file to a flat file. I made this a static method in its own static class (i may put it in a similar utility class down the road) because I will probably end up using it again in another project, so I can now just reference its class without having to instantiate a new object to just call the method. ( I don't need state anyways)
I'm pretty new to programming as well and I hope you found this helpful.
回答5:
If we are going to talk about static, we need to introduce a dependency. In this case it is a sql client. Here's what the code looks like with that introduced. Since we aren't going to get into the details of a sql client it's used as an interface in the static method.
var client = new SqlClient();
var allEmployeeData = EmployeeBal.GetAllEmployees(client);
class EmployeeBal
{
public static Employee GetAllEmployees(ISqlClient client)
{
return client.Execute("Select * from Employee");
}
}
Dependency injection through an interface changes everything. Now the method is good as being static, because it only deals with an interface and a string. Both of these are stateless. Since all components of the method are stateless they are perfectly safe for a static method which can have only one global state.
As your code was written originally it's not safe as being static, because how can I be assured the sql client is prepared to be used and after I've checked that it's ready it hasn't been altered when I go to run the query? If I can inject the sql client I can manage it since it has a local vs global scope.
A better example would be something like a factory for a sql client. For example with nhibernate there should only be one session factory created. That one thread safe session factory can create multiple non-thread safe sessions for running sql queries. In this case it's appropriate to have the session factory exposed through a static method, because that describes the fact that there is only ever going to be one session factory.
var session = SessionFactory.OpenSession();
回答6:
Using static methods is equivalent of having a global behaviour. It comes with benefits: ease of access for simple scenarios.
It also comes with all the problems that global data and state have. Among them you cannot substitute an implementation with another (for example for tests). See https://softwareengineering.stackexchange.com/questions/148108/why-is-global-state-so-evil
While you might consider that you don't have a global state ... conceptually you have. You have a unique, predetermined, unconfigurable, hard coded way of accessing some behaviour. You published it and you cannot change it ... ever. You break the open-close principle. You break the liskov substitution principle.
Java has this but scala amended that. More on this here: Why doesn't Scala have static members inside a class?
回答7:
Use cases for static and non-static methods differ, so you need to create one based on what's the need that they fulfill:
- Static method does not participate in inheritance-based polymorphism, while non-static does. In other words, you can't mark static method as virtual or abstract, which means you cannot change its behavior. This also means that caller of the static method knows exactly what this static method is going to do and how exactly. With non-static method, you can be calling it on base class but due to polymorphism you may end up calling the derived class method with overriden behavior.
- Both static and non-static methods can be changing a state of something (as opposed to what others claim), but there's a difference. You can design a static class that has all static members (properties, methods, etc.) in it, so the methods can be changing the state of this static class (that said, even though
C#
allows you doing that, I don't recommend creating such class anyway). With non-static method, you can be changing both static and non-static state of the class. This goes further into the differences between static and non-static classes, which in short means: static class is one concrete instance, while a non-static class can be multiplied and each of them will have its own copy of the state (so why design a static class with the artificial limitation then - this is why I didn't recommend them before).
- One more nice usage of static methods is extension methods. These should be defined as static, but you can call them on the instance of the class that they are extending. They still serve as outside shortcuts to the instance, since they can't do anything more than regular static methods (cannot access private or protected members for instance).
- And you're right, static class fits well when defining helper methods, because those usually are just shortcuts to some fixed functionality, accessible easily to re-execute it from many places. In Visual Basic, instead of
static
keyword you would use shared
keyword, which nicely explains the purpose of the static method.
Finally, I personally recommend creating static methods as Pure functions, which always produce same output for the same input (no side effects, such as output is different based on time or other implicit factors). You should have a strong reason to design it otherwise (e.g. if you are writing Math.Random()
).
Now, to answer the points from your question (I know, finally):
- I think business access layer should not be static, because you would most likely need benefits of non-static classes, such as dependency injection and unit-testability.
- There is no difference between static and non-static methods from the threading/multithreading standpoint, both of them can be called by multiple threads at the same time and all of them will execute simultaneously (unless using synchronization constructs). However, there is common design recommendation that you should make static methods thread-safe if you expect race conditions. Non-static methods don't have to worry about this, as this would put them into too many assumptions.