Before, going into C# and .NET and stuff, it is better to learn C/C++ man. Not b/c it is easier, but b/c it is more fundamental. Also, C/C++ is more powerful than C# of course.
When u are proficient in C/C++, you will completely understand the meaning of "static" with respect to data and objects, and how it differs. And there are many sources out there for these languages as they have been around for a very long time.
Anyways,
"static" means not changing, but how it translates into objects is different from data types. i.e. static variable vs. static member function of an object.
Object = instance of a Class, can have more than 1
Static variable of a class - indepent of each instance, common to all "instances" (i.e. objects). Maybe keeping "count" of the number of "objects" created of type Class.
Static function of a class - independent of each object. Functionality that is independent of local data of each instance. For example, getting the number of objects created. Or in a "Circle" class, getting the value of pi.
Local static variable wrt functions (C style) - variable retains values "between" function calls. It does not lose the value after function execution. Perhaps keep track of how many times the function was called.
Virtual functions - useful in giving an "interface". The actual implementation details are left to the subclasses. Alternatively, a "base" definition can be created which can be overidden by subclasses. The point is, the calling method gets an interface to call. Depending on the "instance" passed/created that is based on "interface", the correct "sub implementation" gets called. Very difficult for me to explain in one paragraph, as this is a big topic.
BaseClass myvar;
myvar = new SubClass();
myvar.MyClass(5);, will call the function implementation of SubClass and not of BaseClass. And MyClass in BaseClass has to be declared "virtual". Otherwise, it would not be able to "find" the correct sub implementation as the compiler will not create the needed fascility to find it. b/c think about it - myvar is of type BaseClass, otherwise how can it possibly traverse to another type???