Can't read a const in a class instance? - c#

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.

Related

In case i have class with only one static variable - should i declare this class as static?

This is my class how hold my last visited Path:
public class LastPath
{
private static string _lastPath;
public static string lastPath
{
get { return _lastPath; }
set { _lastPath = value; }
}
}
If all members of a class is static and your class is not meant to instantiated it should be static.
In this case your class satisfies the above rule or guideline so marking it as static will make sense because you don't have any instance member.
LastPath path = new LastPath();
path.????// Nothing to access, so prevent instantiation by marking class static.
Being said that If you have only one field in your class and no methods I'd argue that you probably don't need a class at all, just refactor it to some other class where it would make sense.
make the class static and make a public property as static and you are done, like this:
public static class LastPath
{
public static string lastPath { get;set;}
}
I would say you to do this:
public static class LastPath
{
public static string lastPath
{
get;set;
}
}
You should declare it as static as static classes cannot be instantiated, while non static classes can be instantiated, which is not needed.
First - it looks odd to me to create class for holding single variable. Consider to use simple string variable lastVisitedPath instead. If you use this variable in single class, then make it field of that class.
Second - naming is not very readable. Here is how getting last path looks like: LastPath.lastPath. You see this useless duplication? Also keep in mind, that due to Microsoft naming guidelines public members should have Pascal Case names. Consider to create class with descriptive name like GlobalValues or Cache which reflects its purpose:
public static class GlobalValues // holds values which are globally accessible
{
public static string LastVisitedPath;
// other global values
}
So that usage will look like GlobalValues.LastVisitedPath or Cache.LastVisitedPath. Of course, if these classes don't supposed to be instantiated, they should be static.

Accessing a static -kind of field of a of the class of an instance in c#

Sorry for asking such a simple question, but I haven't yet found an answer by searching.
So, is it possible, in c#, to access a field (value of which doesn't need to change) of a class through both an instance of the class and as you would access a static field of the class using the name of the class?
For example if I have
public class Myclass
{
public int a = 0;
}
I want to do elsewhere in the code, in another class
Myclass instance = new Myclass();
int b = instance.a;
and
int c = Myclass.a;
Making int a static or const doesn't help, is there any way to do this? Thanks for any answers.
It's not possible. You cannot access an instance field without an instance of the type, and you can't access a static field through an instance of the type in C#, you need to access it through the type itself.
As far as I know, this is not possible. May be you need to change the way of implementation.
It's not possible to do this, because:
(1) The language prevents you from accessing a static field via an instance reference, and
(2) You cannot have two fields with the same name. (So you can't have a static and a nonstatic field with the same name.)
If MyClass were a Singleton then yes, you could do this, but in your scenario it appears that's going to be a no because you're instantiating it elsewhere. See, if MyClass were a Singleton you could do something like this:
public class MyClass
{
private static MyClass _instance = new MyClass();
public static MyClass Instance { get { return _instance; } }
public int A { get; set; }
public static int a { get { return _instance.A; } }
private MyClass() { }
}
but as you can see it's really hacky. You are really mixing OO concepts here. There is a distinct difference between accessing a static value - MyClass.a - and an instance value. Just deal with creating the instance.
Probably not a good idea, but still, you might be able to do it like this
class Class1
{
public static int staticBlah = 0;
public int blah {
get{return Class1.staticBlah;}
set{Class1.staticBlah = value;}
}
}
Of course, you're not using exactly the same name but you'd be accessing the same variable.

C#, accessing a variable from a class?

Say i have
public int MyVariable;
in the Form1.cs file, and I want to access it from Class1.cs , what do you think would be the best way to do that?
Thanks!
MSDN: Properties
base class with property:
class Person
{
private string name; // the name field
public string Name // the Name property
{
get
{
return name;
}
set
{
name = value;
}
}
}
Auto Implemented Properties (if advanced work on "name" isn't needed):
class Person
{
public string Name { get; set; } // the Name property with hidden backing field
}
Class accessing the property:
Person person = new Person();
person.Name = "Joe"; // the set accessor is invoked here
System.Console.Write(person.Name); // the get accessor is invoked here
It depends on the scenario. But ideally, Form elements are passed to any functions that will need to use them.
You have a few options:
Pass the value to the class/method that's using it. This is the preferred scenario. If your class depends on this value, supply the value to the class. Don't make the class go looking for it. (See: Dependency Inversion Principle)
Make the value static. Then any other class can refer to that value. Note the difference between instance and static, of course. The value will always be the same and needs to be given in the definition of the member, not in a constructor or other logic.
Create an instance of the form (which is itself just a class) within the class and access the public member on that instance. This is unlikely to be what you want because the instance you're creating isn't the instance that's running "on the page." (It also violates the principle noted above.)
Pass a reference to the form (this) to the class and refer to the member from that reference.
On a side note, you'll want to get in the habit of making your public members properties instead of variables. In most cases, the property will likely just get/set the variable and nothing more. However, if something more ever needs to be added it can be done so without breaking compatibility. Changing a variable to a property changes the footprint of the class and breaks things which use that class.
Make the variable static. Then you can call it like Form1.MyVariable.
Try like this:
In case (1) you can have MyClass.MyInt private readonly.
public class MyForm : System.Windows.Forms.Form
{
int myInt;
public MyForm()
{
myInt = 1;
//1
var myClass = new MyClass(myInt);
//2
myClass.MyInt = myInt;
}
}
public class MyClass
{
public int MyInt { get; set; }
public MyClass(int myInt)
{
MyInt = myInt;
}
}

Difference between public and private variables

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.

C#: Can a base class use a derived class's variable in a static function?

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.

Categories

Resources