Sorry about the last post...here is another one.
So far I've seem people use the (.) operator to :
(1) access member of structure
(2) access static/constant member of a class
(3) access literal of a enum-type
(for example, those of dayofweek.cs http://referencesource.microsoft.com/#mscorlib/system/dayofweek.cs)
without having object/instance of that structure/class/enum .
I know that an operator's meaning can depend on its operand;
but some of them looks kind of weird to me.
For example, in the case of (3):
In C#, I can write:
DayOfWeek a;
if (a == DayOfWeek.Sunday) *do something...*;
but in C, I can only write:
DayOfWeek a;
if (a == Sunday) *do something...*.
For another example, in the case of (1):
In C, only after we have an instance of a structure can we do operation to its member;
but in C#, just like in https://stackoverflow.com/questions/24888864/two-things-about-source-code-of-struct-datatime-in-c-sharp, we can directly use NAME(i.e., DataTime) of a structure to access its member(i.e., Maxticks), i.e.,DataTime.Maxticks
There obviously is some difference, right?
Where can I read the thorough tutorial or doc of this operation, saying what how I can use this operation? Only the language spec?
**I actually don't appreciate the way learning that by looking through examples using this operation one-by-one, because they don't tell me "how to use it", but just "what I can do with it"; these two are different, though.
As you have noticed, the . operator is used to access a member.
If that member is marked static, then you can reference it via class name, since there is only ever one static "instance" of a class (and it is instantiated by the runtime). That is what your are seeing with DateTime.MaxTicks.
Enums are not static but their members are accessed the same way, because you need to qualify the member name with the enum name. From the C# spec (v 5.0, section 14.3):
From all other code, the name of an enum member must be qualified with
the name of its enum type. Enum members do not have any declared
accessibility—an enum member is accessible if its containing enum type
is accessible.
One of the uses of . is to qualify something (like when you explicitly declare which namespace a class is coming out of).
Basically, you use . whenever you want to access a member of something. As long as you know if it is an instance or static variable, you'll know if you need an instance of the type or if you can just use the class name. . can also be used to qualify the name of something, which is used when specifying a namespace for a class or using an enum.
In C, only after we have an instance of a structure can we do
operation to its member;
but in C#, just like in Two things about source code of struct
DataTime in c#, we can directly use NAME(i.e., DataTime) of a
structure to access its member(i.e., Maxticks), i.e.,DataTime.Maxticks
There obviously is some difference, right?
We can use the name of class and then dot and the method we want to call, when the method of the class is a static method. In this case the method belongs to the class and not to the objects we create using the new keyword.
From the C# specification:
A method is a member that implements a computation or action that can
be performed by an object or class. Static methods are accessed
through the class. Instance methods are accessed through instances of
the class.
One of the best explanations about the static keyword can be found in MSDN.
As for the access of the members of a struct in C#, you use the same operator you use to access the members of a class in C#, the dot operator. This is the reason, why you need DayOfWeek.Sunday.
Think of it as navigating the namespace. Your project structure could be:
MyApp
Forms
MainForm
ShowForm()
IsOpen()
Classes
SomeClass
SomeStaticMethod()
NonStaticMethod()
OtherClass
SomeEnum
EnumValueOne
EnumValueTwo
Repositories
ThisRepo
All of this would be called, imported, or accessed a similar way using dot notation despite their different purposes and structures. Calling the static ShowForm() void on MainForm would be MyApp.Forms.MainForm.ShowForm(), just like referencing an enum in OtherClass would be done like MyApp.Classes.OtherClass.SomeEnum.EnumValueTwo.
You obviously won't need to do the full qualifying namespace when you add a using statement to your class, but hopefully this shows the concept.
Related
I can imagine the first reaction when you read the title of my question: "How can you have such a high reputation here and ignore what a class is?"
My point is the following: until now I have always worked with C++, Delphi, Java, ... and there it's quite simple: a class is a type definition of an object. You need to reserve some space in memory to start using it (hence the constructor) and afterwards, don't forget to free that memory (if your programming language does not support garbage collection).
Today, however, I had a problem concerning type definitions and constants in C#, and I fell on this URL, mentioning such pieces of source code:
class Calendar1
{
public const int Months = 12;
}
In order to use this, you just need to do:
using Calendar1;
And you can use Months as a constant.
But here's my question: where's the constructor? If this class is the type definition of an object, which object are we talking about?
So, if I understand correctly, C# is based on the idea "Everything is a class", but in order to make this work, the C# inventors have extended the definition of a class, so now we get (C# definition):
A class is one of the following:
a type definition for an object. In that case, a constructor is needed for creating the object.
...
Can somebody finish the definition?
This is a pretty common practice in C#. Classes are often used to create "sacks" to hold constants, or commonly as a entity or dto object. These are usually made without a user defined constructor. If a class does not have a constructor, one is defined at compile time which amounts to an empty constructor:
public Calendar1()
{
}
This answer goes into much further detail:
C# class without constructor
You don't need this using. using is to make namespaces available.
A constant is static. This means that it is not an instance member but a member of the type. Thus, you can access it through the type name: Calendar1.Months or, with a using static Calendar1; just with Months.
In C# a class implicitly creates a parameterless public constructor, if you don't declare one explicitly.
When you are creating a instance of a class you are allocating memory (using the keyword new)
Constants are created not in runtime, they are created in compile time and stored in the assembly metadata. So when you are accessing a constant you will be not accessing an instance of a class - you will be accessing the constant from the metadata directly.
Have a look at this post:
How are C# const members allocated in memory?
Is there a keyword to refer to the current class type similar to how this refers to the current instance?
My intention is to avoid having to type the full class name when refering to static members or Enums but I want to prefex it with something like "this" for readability like I do for instance members. The reason being some of the class names are pretty huge and cause excessive wrapping.
I don't think there's a keyword, but maybe as good:
this.GetType();
GetType is one of the few methods implemented by System.Object.
If you include the namespace with using, you won't indeed to enter the full path.
You can alias the class names with using, for instance:
using ClassA = Really.Deep.Class.In.Namepsace.For.SomePurpose.ClassA;
typeof(this) will do what you're after.
Edit:
I stand corrected. typeof(this) isn't valid C#. dbaseman is correct: this.GetType() will work.
Using C# as an example. Say there is a class named ExampleClass and the variable is just value. Why would one declare a variable like this
private ExampleClass value;
You wouldn't declare a variable named value unless there was some unavoidable requirement to do so.
The reason why is because it is not meaningfully named.
When we name variables meaningfully, our code becomes self-documenting. Well documented code is always worthy goal.
This is a field and can be declared inside a class. Example:
private class Test
{
private int _customField;
}
_customField is my field with type int (instead of ExampleClass). People use it to make something more accessible since C# isn't just functions, it's OOP.
There is a thing called Primitive Obsession. Using a class/specific type here is the solution to it.
If you use a class, you got all the Compiler Type checking to help you avoid invalid values.
Take this Enum vs Integer question for examples.
Because sometimes, I really need a friend.
I can think of the following tricks:
Read only wrapper - like ReadOnlyCollection. The friend keeps the pointer to the modifiable object, while everyone else can access only the wrapper.
Write delegate - the friend gives the constructor of the object a reference to a delegate as one of the parameters, the constructor fills it with an address to a private method that can be used to modify the object.
Reflection - obviously a bad idea. Included for completeness.
Multiple assemblies - put your friends together in a separate assembly and set your modifier methods internal.
Expose the modifiable object, but add comments to modifier methods "This is an infrastructure method - don't call it!"
Nested classes.
Add System.ComponentModel.EditorBrowsable(System.ComponentModel.
EditorBrowsableState.Never) attribute to the member you want only the friend to access to hide it from IntelliSense.
Implicit interface implementation - see comments.
Is this list exhaustive? Can anyone sort these in order of decreasing performance? Order of decreasing neatness? Any suggestions when to use which?
You can also use the InternalsVisibleTo attribute.
For a given assembly, A, you can specify which other assemblies can have access to A's internal types.
In c# Nested classes (like private classes) are similar to friend in c++:
public class Root
{
private int a; // accessible for friendroot
public int b;
public class FriendOfRoot
{
public int d;
}
}
Edit: If the simulation of friend with nested classes provided here is useful for you, in performance it's fast enough like regular classes (In compile all things will be determined and there is no casting issues and no overhead).
This is more of a documentation than a real question. This does not seem to have been addressed on SO yet (unless I missed it), so here goes:
Imagine a generic class that contains a static member:
class Foo<T> {
public static int member;
}
Is there a new instance of the member for each specific class, or is there only a single instance for all Foo-type classes?
It can easily be verified by code like this:
Foo<int>.member = 1;
Foo<string>.member = 2;
Console.WriteLine (Foo<int>.member);
What is the result, and where is this behavior documented?
A static field is shared across all instances of the same type. Foo<int> and Foo<string> are two different types. This can be proven by the following line of code:
// this prints "False"
Console.WriteLine(typeof(Foo<int>) == typeof(Foo<string>));
As for where this is documented, the following is found in section 1.6.5 Fields of the C# Language Specification (for C# 3):
A static field identifies exactly one
storage location. No matter how many
instances of a class are created,
there is only ever one copy of a
static field.
As stated before; Foo<int> and Foo<string> are not the same class; they are two different classes constructed from the same generic class. How this happens is outlined in section 4.4 of the above mentioned document:
A generic type declaration, by itself,
denotes an unbound generic type that
is used as a “blueprint” to form many
different types, by way of applying
type arguments.
The problem here is actually the fact that "generic classes" are not classes at all.
Generic class definitions are just templates for classes, and until their type parameters are specified, they are just a piece of text (or a handful of bytes).
At runtime, one can specify a type parameter for the template, thus bringing it to life, and creating a class of the, now, fully specified type. That's why static properties are not template-wide, and that's why you cannot cast between List<string> and List<int>.
That relationship kinda mirrors the class-object relationship. Just like classes do not exist* until you instantiate an object from them, generic classes do not exist, until you make a class based on the template.
P.S. It's quite possible to declare
class Foo<T> {
public static T Member;
}
From this is kinda obvious that the static members cannot be shared, as T is different for different specializations.
They are not shared. Not sure where it's documented but analysis warning CA1000 (Do not declare static members on generic types) warns against just this due to the risk of making the code more complicated.
C# implementation of generics is more closer to C++. In both of these languages MyClass<Foo> and MyClass<Bar> don't share static members but in Java they do. In C# and C++ MyClass<Foo> internally creates entirely new type at compile time as if generics are kind of macros. You can usually see their generated names in stack trace, like MyClass'1 and MyClass'2. This is why they don't share static variables. In Java, generics are implemented by more simpler method of compiler generating code using non-generic types and adding type casts all over. So MyClass<Foo> and MyClass<Bar> don't generate two entirely new class in Java, instead they both are same class MyClass underneath and that's why they share static variables.
They are not really shared.
Because the member doesn't belong to the instance at all.
A static class member belongs to the class itself.
So, if you have MyClass.Number it is the same for all MyClass.Number objects because it not even depends on the object.
You can even call or modify MyClass.Number without any object.
But since Foo< int > is not the same class as Foo< string > these two numbers are not shared.
An example to show this:
TestClass<string>.Number = 5;
TestClass<int>.Number = 3;
Console.WriteLine(TestClass<string>.Number); //prints 5
Console.WriteLine(TestClass<int>.Number); //prints 3
IMO, you need to test it, but I think that
Foo<int>.member = 1;
Foo<string>.member = 2;
Console.WriteLine (Foo<int>.member);
will output 1 because I think that, during compilation, the compilator create 1 class for every generic class you use (in you example : Foo<int> and Foo<string>).
But I'm not 100% sure =).
Remark : I think it's not a good design nor a good practice to use such kind of static attributes.