namespace hi
{
class hithere
{
public int numberOne = 12;
private int numberTwo = 12;
static void yo()
{
}
}
}
Can someone tell me the difference between the variables numberOne and numberTwo in this code excerpt?
From the accessibility levels at MSDN:
public Access is not restricted.
protected Access is limited to the containing class or types derived from
the containing class.
internal Access is limited to the current assembly.
protected internal Access is limited to the current assembly or
types derived from the containing
class.
private Access is limited to the containing type.
Public variables are accessible from out side classes but private one just accessible for current class and inner classes:
public class VarClass
{
public int publicID = 10;
private int privateID = 100;
public VarClass()
{
Console.WriteLine(publicID);
Console.WriteLine(privateID);
}
public class InnerClass
{
public InnerClass()
{
VarClass c = new VarClass();
Console.WriteLine(c.privateID);
Console.WriteLine(c.publicID);
}
}
}
public class OuterClass
{
public OuterClass()
{
VarClass c = new VarClass();
Console.WriteLine(c.privateID); // Compile Error
Console.WriteLine(c.publicID);
}
}
Other objects can access NumberOne, but they can't access numberTwo.
So I can do Your_Object.numberOne = 14; but I can't do Your_Object.numberTwo= 14;
Now I might be able to access the numberTwo through reflection depending on the permissions set up in the application, but I can't directly.
Variables in C#
Reflection in C#
Accessors in C#
in general, PUBLIC means any other code outside the class can change its value. PRIVATE are only able to be used/changed IN the class itself. Additionally, if you build classes that are derived from another, and you want the child-level class to be able to use/change values of its parent, but not other generic code outside the class, use PROTECTED.
Search for "Encapsulation".
There are so many easy materials to study it.
In the simplest terms numberOne being marked as public means that if you create an instance of your hithere class this member variable will be accessible. For example:
hithere h = new hithere()
h.numberOne = 42;
numberTwo being private means that this is not accessible and can only be used within the hithere class. So taking the above example further:
hithere h = new hithere()
h.numberOne = 42;
h.numberTwo = 84;
The last line would cause a compiler error as you cannot access numberTwo as this is private.
It is probably worth spending some time reading up on access modifiers, a quick google will find many examples, e.g:
http://www.devsource.com/c/a/Techniques/Understanding-C-Class-and-Member-Modifiers/
http://msdn.microsoft.com/en-us/library/ba0a1yw2%28v=vs.80%29.aspx
Additionally your hithere class does not have an access modifier defined therefore the compiler assumes this to be private. As such if you were to reference your library from another you would not be able to create instances of the hithere class.
public and private are access modifiers for members. This refers to who can access the members directly through code. public means that access is not limited so that anyone can access the member directly through code. private means that access is limited only to the containing class. So everyone can access numberOne directly through code, but only the containing class can access numberTwo directly through code.
There are a total of five access modifiers:
public: access is not limited
protected: access is limited to the containing class or classes derived from the containing class
internal: access is limited to the containing assembly
protected internal: this is an OR of protected and internal so that access is limited to the containing class or classes derived from the containing class OR the containing assembly
private: access is limited to the containing class
Note that the clause "directly through code" is critical here; it is possible to access these members using reflection.
The relevant section of the C# specification is §3.5, especially §3.5.2.
It means that if you have another class like this:
namespace hi
{
class hithere2
{
static void yo2()
{
hithere h = new hithere();
h.numberOne = 2;
h.numberTwo = 3;
}
}
}
The second one errors, but the first is OK.
Related
I'm a little bit confused with nameof() operator. So for example I can't use class's private fields in nameof() in another class, but I can use public non static fields using non static property, so I don't need instantiated object.
Is it consistently? Why member access modifier does matter for nameof()?
class A
{
private int X;
public int Y;
public A()
{
var x = nameof(A.X);//OK
var y = nameof(A.Y);//OK
}
}
class B
{
public B()
{
var x = nameof(A.X);//Compilation error
var y = nameof(A.Y);//OK
}
}
The purpose of access modifiers like private is to hide the implementation details. They are saying "Nope, you don't need to know this. This is implementation detail". That's why nameof is not allowed to access private properties. Whatever class you are in, that class should not know about the implementation details of some other class.
Static vs non-static is different. Its purpose is not to hide something that you don't need to know about. Its purpose is just to distinguish between members that belongs to instances of the class and members that belongs to the class itself. All you want here is just the name of that member, which requires no instances to be created, so why disallow you? Note that the member is accessible i.e. it's not something you shouldn't know about.
Field X in class A is private. door is locked, you cant access it no matter what you do.
This is not a nameof problem, its Access Modifier problem
Access Modifiers (C# Programming Guide)
All types and type members have an accessibility level, which controls
whether they can be used from other code in your assembly or other
assemblies. You can use the following access modifiers to specify the
accessibility of a type or member when you declare it:
and
public The type or member can be accessed by any other code in the same assembly or another assembly that references it.
private
The type or member can be accessed only by code in the same class or struct.
protected The type or member can be accessed only by code in the same class, or in a class that is derived from that class. internal
The type or member can be accessed by any code in the same assembly,
but not from another assembly.
protected internal The type or member can be accessed by any code in the assembly in which it is declared, or from within a derived class
in another assembly.
private protected The type or member can be accessed only within its declaring assembly, by code in the same class or in a type that is
derived from that class.
Not a direct answer to your question, but I usually get around this but using a static helper class:
class A
{
public static class Properties
{
public const string X = nameof(A.X);
}
private string X { get; }
}
Then using
A.Properties.X
It's a little bit more verbose, but still enables refactoring tools to work effectively.
An example is worth a thousand stupid questions so:
public class OuterClass
{
public static class InnerClassEventArgs : EventArgs
{
public static int SomeInt;
}
}
and in a galaxy far far away:
public void SomeFunkyFunc()
{
OuterClass Instance1;
OuterClass Instance2;
Instance1.InnerClassEventArgs.SomeInt = 1;
Instance2.InnerClassEventArgs.SomeInt = 2;
//WHAT WOULD Instance1.InnerClassEventArgs.Someint == ?
}
Yes, I realize now that I've typed this that I've almost coded all I need to answer my own question. I'd rather not create a new project and go through the trouble if someone smarter than me knows off the top of their head.
Instance1.InnerClassEventArgs.SomeInt would equal 2. Static fields are shared across all instances of the class -- or as MSDN puts it:
The static member is always accessed by the class name, not the instance name. Only one copy of a static member exists, regardless of how many instances of the class are created.
Note that your specific example won't compile -- you'll get an error message that says "Cannot access static class 'InnerClassEventArgs' in a non-static context."
You'd have to use the following code instead, which hopefully makes the behavior more understandable:
OuterClass.InnerClassEventArgs.SomeInt = 1;
OuterClass.InnerClassEventArgs.SomeInt = 2;
A static class has exactly one instance, "shared" by all its usages (in your case, all instances of OuterClass). Therefore, the state of that object will be the sum of all changes made by any usage. In this simple example, SomeInt will be 2, regardless of which OuterClass instance you used to access it again (Instance1 or Instance2).
I'm conveniently ignoring all of the following:
A static class cannot inherit from any other class. InnerClassEventArgs thus cannot inherit from EventArgs.
Instance1 and Instance2 are not initialized; this will cause its own compile-time error if you use ReSharper ("X may not be initialized before accessing").
Static members (including nested static classes) cannot be accessed based on any one instance; you would access InnerClassEventArgs in static context.
I was mildly surprised when the compiler complained about this:
public class UsefulClass
{
public const String RatingName = #"Ratings\rating";
}
public class OtherClass
{
public void SomeFunc()
{
UsefulClass useful = new UsefulClass();
String rating = useful.RatingName;
}
}
Compiler says, "Static member cannot be accessed with an instance reference; qualify it with a type name instead"
This isn't a problem, String rating = UsefulClass.RatingName; works fine. I'm just curious what the thinking is behind this? I have an instance of a public class with a public constant on it, why can't I get the data this way?
Because constants just aren't instance members; they're statically bound to their respective types. In the same way you can't invoke static methods using instances, you can't access class constants using instances.
If you need to get a constant off an instance without knowing its type first-hand, I suppose you could do it with reflection based on its type.
If you're trying to add a member that can't be modified but pertains to instances, you probably want read-only fields or properties instead.
A "variable" marked const is a compile time construct, not an instance member. You can access it like you would a static variable:
public void SomeFunc()
{
UsefulClass useful = new UsefulClass();
String rating = UsefulClass.RatingName; // Access as if static
}
That being said, I would personally wrap this into a property if it's meant to be used as you described, like so:
public class UsefulClass
{
private const string ratingName = #"Ratings\rating";
public string RatingName { get { return ratingName; } }
}
This would make your syntax work, but also be a better design, IMO, since it doesn't expose your constants publically.
Because const in c# are implicitly of static type. And As static members can be accessed only on class member and not on instance, const cannot too.
We cannot access a private variable of a class from an object, which is created outside the class, but it is possible to access when the same object is created inside the class, itself. why??
class Program
{
private int i;
public void method1()
{
Program p = new Program();
p.i = 5; // OK when accessed within the class
}
}
class AnotherClass
{
void method2()
{
Program p = new Program();
p.i = 5; //error because private variables cannot be accessed with an object which is created out side the class
}
}
Now I think every one got my point??
In both the cases above, we are accessing the private variable 'i' through the object 'p'. But inside class it is allowed, outside the class not allowed. Can anybody tell me the reason behind this??
You can access i from within the class because private members can only be accessed by members of the class. In this case it looks strange because p is a different object than the object that accesses the variable, but its still the same class and the restriction is on the class level not on the object level.
class Program
{
private int i;
public void method1()
{
Program p = new Program();
p.i = 5; // OK when accessed within the class
}
}
You can not access i from within another class (unless it is an inner class but that's a different story). Which is completely as expected.
class AnotherClass
{
void method2()
{
Program p = new Program();
p.i = 5; //error because private variables cannot be accessed with an object which is created out side the class
}
}
I understand the point you want to make. The restriction on class level looks counter intuitively. And maybe this is wrong. But the member variables are still only accessible from within the class, so you still have total control to guarantee the encapsulation of your privates.
why??
It's true by the language specification. The access modifier private has the semantics that only the class or struct declaring a member is allowed to access that member.
I suggest reading the specification for details. In particular, check out
§3.5.1 Declared Accessibility
§3.5.4 Accessibility constraints
§10.2.3 Access Modifiers
§10.2.6.2 Declared Accessibility
§10.2.6.5 Access to private and protected members of the containing type
In both the cases above, we are accessing the private variable 'i' through the object 'p'. But inside class it is allowed, outside the class not allowed. Can anybody tell me the reason behind this??
Because access modifiers don't pertain to the object, they pertain to the class (or assembly, for the internal modifier).
Even if you access it from a different object, or a static context, as long as you stay in the same class, accessing a private member will work. It's private to the class, not its instances.
You are maybe confusing object and class, public/private/protected/internal affect class visibility not object visibility. That means an object of a class can access attributes of another object of the same class, even if they are private.
I am not sure I understood your question correctly...
if accessing outside the class is the option required then try properties.
This belongs to OOP. The answer would be because its private, otherwise if all private variables would be accessable from outside the class the object's concept wouldnt make any sense.
You Can Access the private variables in the following process also...
namespace OOPSProj
{
class Program
{
private int i;
public void Methode1()
{
Program objprog2 = new Program();
objprog2.i = 15;
Console.WriteLine("i= " + objprog2.i);
}
static void Main(string[] args)
{
Program objprog = new Program();
objprog.i = 10;
Console.WriteLine("i= " + objprog.i);
objprog.Methode1();
}
}
class Test
{
static void Main()
{
Program objproj3 = new Program();
objproj3.Methode1();
}
}
}
Is there anyway of having a base class use a derived class's static variable in C#? Something like this:
class Program
{
static void Main(string[] args)
{
int Result = DerivedClass.DoubleNumber();
Console.WriteLine(Result.ToString()); // Returns 0
}
}
class BaseClass
{
public static int MyNumber;
public static int DoubleNumber()
{
return (MyNumber*2);
}
}
class DerivedClass : BaseClass
{
public new static int MyNumber = 5;
}
I'm trying to have it return 10, but I'm getting 0.
Here's where I'm using this: I have a class called ProfilePictures with a static function called GetTempSavePath, which takes a user id as an argument and returns a physical path to the temp file. The path base is a static variable called TempPath. Since I'm using this class in multiple projects and they have different TempPaths, I'm creating a derived class that sets that variable to whatever the path is for the project.
See Also
Why can’t I declare C# methods virtual and static?
Apart from the fact that has already been pointed out... that static variables are tied or bound to the specific class declaring them and cannot be overridden. Overriding/Polymorphism needs instances to work.
Your problem can be solved with a change in design.
string ProfilePictures.GetTempSavePath(SomeType UserId, string sBasePath)
if it just needs these 2 variables to compute the return value, you can keep it as a utility/static method. Now you can feed in different base paths..
Now it seems from your question, that you need to use this class in multiple projects (which have fixed base paths) and kind of hardcode the base path so that you dont have to specify it for each call.
Type/Class hierarchies should be defined based on behavior and not on data. Variables can handle change in data. Hence I'd suggest holding the basepath value as a static member variable, which is initialized from a resource file (DoubleClick your project properties node > Settings > Add a new Settings file > add a new setting called BasePath - string - Application scope - VALUE=C:\Users). Now you just need to tweak the app.config file for each project, no code changes, no hardcoding and not more than one type needed.
public class PathHelper
{
static string _sBasePath;
static PathHelper()
{
_sBasePath = Properties.Settings.Default.BasePath;
}
static string GetTempSavePath(string sUserId)
{
// dummy logic to compute return value, replace to taste
return Path.Combine(_sBasePath, sUserId.Substring(0, 4));
}
}
Hope that made sense
The problem is that you're re-declaring the static variable in the derived class. The MyNumber declaration in DerivedClass hides the declaration in the base class. If you remove that declaration, then references to the "MyNumber" in derived class static functions will refer to the base class variable. Of course, if you remove the declaration then you can't use a static initializer in the derived class.
You might want to consider requiring users to instantiate an instance of ProfilePictures rather than provide a static function for GetTempSavePath. That way you could overide the GetTempSavePath method to provide the correct TempPath. Or, you could simply set the value of the static path value in your derived class constructor.
Although it is possible to use inheritance with static members, you can't relly have polymorphic behavior without a "this" pointer.
Static members are not virtual, so you can not override them.
When you call DerivedClass.DoubleNumber you are actually calling BaseClass.DoubleNumber as the DerivedClass class doesn't have that method. Also, the use of MyNumber in that method is always going to be BaseClass.MyNumber no matter how you call the method.
What you are looking for is a virtual property that you can override in a derived class. As a virtual member can not be static, you need to use an instance of the class. If it's not practical to keep a reference to the instance, you can use the singleton pattern.
This kinda works:
public class ClassA
{
protected static int num = 5;
public static int GetNum()
{
return num;
}
}
public class ClassB : ClassA
{
static ClassB()
{
num = 6;
}
}
However, note the difference when you call ClassB.GetNum() before and after instantiating one object. The static initializer doesn't run until you create at least one, so you'll get 5 if nothing has been created, and 6 if at least one object has.
Provide a virtual method that returns the class static.
class BaseClass
{
public virtual int GetMyNumber() { return MyNumber; }
}
You might want to use a virtual property instead...
Using too much of static members is also not recommended if they are going to encapsulate a logic of an entire object. For example your code can be rewritten correctly in following manner... and this is the most recommended in oops,
class Program
{
static void Main(string[] args)
{
int Result = DerivedClass.Instance.DoubleNumber();
Console.WriteLine(Result.ToString()); // Returns 0
}
}
class BaseClass
{
protected BaseClass(){} // this enforces that it can not be created
public int MyNumber;
public virtual int DoubleNumber()
{
return (MyNumber*2);
}
}
public class DerivedClass : BaseClass
{
// this also ensures that it can not be created outside
protected DerivedClass(){
MyNumber = 5;
}
// only way to access this is by Instance member...
public static DerivedClass Instance = new DerivedClass();
}
This is how we access configuration values and many other single instance static objects provided by .Net Library.