Doesn't object initialization outside of a constructor break encapsulation ?
Given:
class MyClass
{
public string _aString;
}
Shouldn't the _aString member be private and instantiated via a call to the constructor (constructor omitted here):
MyClass test = new MyClass("test");
Instead of the alternate method of object initialization:
MyClass test = new MyClass { _aString = "Test" };
"Doesn't object initialization outside of a constructor break encapsulation ?"
Well, no. As you rightly pointed out you can only initialize properties that are already accessible in your current scope. (public, internal etc)
This kind of Intialization is really just some syntactic sugar around construction of a class and assigning values to properties, It is very useful for Anonymous classes and Linq select clauses.
It is usually considered bad practice to expose public fields... it may be acceptable in some cases, for instance if the field is marked as readonly (which means it must be set in the constructor). Instead, you should make this field private and expose it through a property, which may or may not be readonly, depending on its purpose :
class MyClass
{
private string _aString;
public string AString
{
get { return _aString; }
// uncomment to make the property writable
//set { _aString = value; }
}
}
If you consider Properties as getters and setters, I don't believe it will break encapsulation. But you should notice that you didn't use a Property, you have used an instance variable. In fact, I don't believe it will work like your example. Check this one:
class MyClass {
private string aString;
public string AString {
get { return aString; }
set {aString = value; }
}
}
MyClass test = new MyClass {
AString = "test"
};
In this case, you are accessing the private field through it's accessor. It's just like using a parameterless constructor and setting the value later.
It depends on the purpose of the variable. If the programmer should only be able to set the variable at initialization, but then not have access to it after that, then I would go with the private variable. If you want the class user to be able to set / read the variable at any time, then make it public.
When you have
public string _aString;
it really does not matter when you initialize this value since this is already exposed. So, when we want to talk about initialization we should move this string into property. Than talkin about encapsutlation makes sense.
So, imagine we have some string. There are mosly two approaches to initializatnion. One is to do it inside constructor, second is lazy initialization (initialize when some request this data).
yes, initialize via the constructor, and add properties to allow (or not) access to the data.
class MyClass {
private string _aString;
string MyProperty {
get { return this._aString; }
// you can make this private or protected
set { this._aString = value; }
}
}
If you're asking if the new object initialization shorthand breaks encapsulation, then the answer is no. You can only set publicly scoped members with the new method.
MyClass test = new MyClass { _aString = "Test" };
is the same as
MyClass test = new MyClass();
test._aString = "Test";
To show an object public in a C# class does not break "encapsulation" from a point of view of "Object-oriented programming".
From a point of view of a "good practise" it not a good thing, use Properties because it allows to external code to use this class if you change the behaviour of updating this value (checking, ...).
Related
I'm building a WPF application in C#, and i have a question about the way getters and setters for class instances and their properties work; given the following code:
public class SomeClass
{
public int SomeProperty;
}
private SomeClass _anInstance;
public SomeClass anInstance
{
get{ return _anInstance; }
set
{
_anInstance = value;
}
}
anInstance = new SomeClass();
anInstance.SomeProperty = 5;
int anInt = anInstance.SomeProperty;
I'd expect this code to create at least one instance of the SomeClass, then to assign 5 to _anInstance.SomeProperty, and then set anInt to the value of _anInstance.SomeProperty but i'm not sure if it's using anInstance.SomeProperty or _anInstance.SomeProperty.
Which one is being assigned to 5/used to set anInt, and, for future reference, how would i be able to find out/know?
how would i be able to find out/know?
Set breakpoints and step into your code. The debugger will show you where the execution currently is.
Your public property anInstance's getters and setters just point to the private _anInstance field, and "redirect" reads and writes to that.
Since SomeClass is a Reference Type, anInstance is just a public reference to the same object _anInstance refers to. There is only one instance of SomeClass.
So I have an object called FixedSizeList that does not have a parameterless constructor.
Looks like this.
class FixedSizeList<T>
{
public FixedSizeList(Int32 size)
{
this.Size = size;
this._Array = new T[size];
}
}
Now I want to use this object as a property of another class as such.
public FixedSizeList<Card> CardList { get; set; }
I have noticed that I can infact declare the property with a constructor.
public new FixedSizeList<Card> CardList { get; set; }
But the problem is that the FixedSizeList is not instantiated (I guess for obvious reasons).
So shouldn't I either get a compile time error (something like "No parameterless constructor declared for object") for this code or infact be somehow able to declare the parameter in the property?
Could someone please explain what is going on and if there is someway to fix this problem?(Obviously I can do all this in the constructor of the second object but I am trying to look at other techniques).
Putting new in front of a property doesn't cause the property's setter to be magically called at initialization time and passed a new instance of that type (that would be quite a load of implications for a tiny little keyword!)
Rather, it's used to hide a member with the same name on a base class.
If you want your property to return a new instance right away, you need to give it a backing that's initialized:
public FixedSizeList<Card> CardList
{
get { return _cardList; }
set { _cardList = value; }
}
private FixedSizeList<Card> _cardList = new FixedSizeList<Card>(99999999);
what you want to do is something of a factory
you need a static method that will return you an instance of the object, inside your class
public static FixedListSize GetInstance() {
return new FixedListSize();
}
I can't remember though if you have to mark the class as static, i think you may have to. it's escaping me at the moment :\
I'm pretty new to C# and I was trying out a few things. I have a label (named 'newLabel') in the form1.cs. I have a class named 'methods.cs'. In this class I have the method
public static void updateLabel()
what I want to do is:
public static void updateLabel()
{
newLabel.Text = "New Value";
}
but this doesn't work, probably because the method is in methods.cs and the newLabel is in form1.cs.
I had the same problem with declared variables. In the methods.cs I had the variable
int value;
but I couldn't use this variable in form1.cs. I fixed this by doing
public static int value { get; set; }
I have no idea what that did but it works, but I don't know how I can apply this trick with the label.
Could someone help me with this?
Thanks!
You should read up about OOP and encapsulation. Basically you want the form
to access private fields in another object (your class) - this is restricted by encapsulation, that's why you are running into problem - you can get around them by adding those fields and methods to the "public" interface that your class is declaring by making them public properties and methods, i.e in your example:
public int Value {get;set;}
Sometimes composition is used, i.e. in your example since your class is directly accessing the form you could have a form property on your class:
public Form ViewForm {get;set;}
It would be best if you learnt C# from tutorials, but the answer to this particular question lies with something called "scope"
Essentially, scope is the visibility of variables, classes, functions and objects. A variable marked "private" can only be seen within the thing that created it (if it's created inside a function it will always be private and any variables defined inside a function can only be used inside that function). If it's created inside a class only that class can use it.
Variables or functions denoted as public (this can only be done inside a class) can be seen from outside that class. To do that you would invoke myClass.myVariable to access the variable or myClass.myFunction() to access the function.
To denote the visibility of an object you use the keywords "public" or "private". Note: This only applies to variables and functions inside classes (it also applies to other things within classes, such as nested classes and structs, but that's outside the scope of this basic intro).
for example:
class myClass
{
private int myInt;
public void myfunction()
{
myInt = 1;
}
}
This will work, as myInt can be seen by anything inside myClass
class myOtherClass
{
private void myfunction()
{
myClass myObject = new myClass();
myObject.myInt = 2;
}
}
This will not, as myInt is private to myObject and only myObject can change it. myOtherClass does not have permission and it cannot see it.
class myOtherClassTwo
{
private void myfunction()
{
myClass myObject = new myClass();
myObject.myFunction();
}
}
This, thankfully, will work. myFunction was set as public in the myClass class, so it can be seen by anybody outside of the class.
Now the keyword static which you use has a whole different meaning. I advise you not to use it until you've learned about it as you're only adding additional complexity to your problems.
I hope this has cleared things up, though I must urge you to follow some real tutorials as these basics must be thoroughly detailed or you'll be caught out later on.
Since your updateLabel method accesses the label inside the form, correct object-oriented design would dictate that this method should be in the form, too. Then you have no problem accessing newLabel.
Technically speaking: newLabel doesn’t mean anything outside a form object. You could have several copies of your form, which would mean several copies of your newLabel; which of them should it refer to? Of course the computer won’t take a guess there; it’ll expect that you tell it which form you want to use.
The reason you couldn’t access the value variable is because it was private. If you had changed it simply to:
public static int value;
then it would have worked.
From the Form1, call the updateLabel method in the mothods class:
methods updateMethod = new methods();
newLabel.Text = updateMethod.updateLabel();
With this method in the methods class:
public static string updateLabel(){
return "New Value";
}
In almost all of my classes, I have a mixture of properties and internal class variables. I have always chosen one or the other by the rule "property if you need it externally, class variable if not". But there are many other issues which make me rethink this often, e.g.:
at some point I want to use an internal variable from outside the class, so I have to refactor it into a property which makes me wonder why I don't just make all my internal variables properties in case I have to access them externally anyway, since most classes are internal classes anyway it aren't exposed on an API so it doesn't really matter if the internal variables are accessible from outside the class or not
but then since C# doesn't allow you to instantiate e.g. List<string> property in the definition, then these properties have to be initialized in every possible constructor, so these variables I would rather have internal variables just to keep things cleaner in that they are all initialized in one place
C# code reads more cleanly if constructor/method parameters are camel case and you assign them to pascal case properties instead of the ambiguity of seeing templateIdCode and having to look around to see if it is a local variable, method parameter or internal class variable, e.g. it is easier when you see TemplateIdCode = templateIdCode that this is a parameter being assigned to a class property. This would be an argument for always using only properties on internal classes.
e.g.:
public class TextFile
{
private string templateIdCode;
private string absoluteTemplatePathAndFileName;
private string absoluteOutputDirectory;
private List<string> listItems = new List<string>();
public string Content { get; set; }
public List<string> ReportItems { get; set; }
public TextFile(string templateIdCode)
{
this.templateIdCode = templateIdCode;
ReportItems = new List<string>();
Initialize();
}
...
When creating internal (non-API) classes, what are your strategies in deciding if you should create an internal class variable or a property?
If I have a private variable that I find needs public access at a later point, I just create a property that uses it as it's private member, ex:
private List<string> listItems = new List<string>();
Public List<string> ListItems
{
get{return listItems;}
set{listItems = value;}
}
This allows you to create public access to the data, without having to refactor any code. It also allows you to initialize the data in the private member, and not have to do it in the constructor.
One more advantage is that any modifications to the data that you want to perform for anyone accessing the public property, can be done in the property's getter.
Even though VS2008 introduced Automatic Properties as a feature, I still prefer the VS2005 style of properties.
All I need is a way to make a property of one class only 'settable' from one other class (a sort of manager class).
Is this even possible in c#?
My colleague 'reliably' informs me that I have a design flaw, but I feel I should at least ask the community before I concede defeat!
No, it's not really possible to do this in any clean way in C#. You probably have a design flaw ;-)
You can use the internal modifier, which lets all types in the same assembly access the data (or nominated assemblies if using [InternalsVisibleTo] - but no: there is no friend equivalent in C#.
For example:
public string Foo {get; internal set;}
You have a design flaw. Also, don't be paranoid about data hiding. Here's 3.5's way to do it:
class Program
{
static void Main(string[] args)
{
Managed m = new Managed();
Console.WriteLine(m.PrivateSetter);
m.Mgr.SetProperty("lol");
Console.WriteLine(m.PrivateSetter);
Console.Read();
}
}
public class Managed
{
private Manager _mgr;
public Manager Mgr
{
get { return _mgr ?? (_mgr = new Manager(s => PrivateSetter = s)); }
}
public string PrivateSetter { get; private set; }
public Managed()
{
PrivateSetter = "Unset";
}
}
public class Manager
{
private Action<string> _setPrivateProperty;
public Manager(Action<string> setter)
{
_setPrivateProperty = setter;
}
public void SetProperty(string value)
{
_setPrivateProperty(value);
}
}
Here's how we'd do it in pre-lambda days:
public class Managed
{
private Manager _mgr;
public Manager Mgr
{
get { return _mgr ?? (_mgr = new Manager(this)); }
}
public string PrivateSetter { get; private set; }
public Managed()
{
PrivateSetter = "Unset";
}
public class Manager
{
public void SetProperty(string value)
{
m.PrivateSetter = value;
}
private Managed m;
public Manager(Managed man)
{
m = man;
}
}
}
The best way to do it would be:
/// <summary>
/// Gets or sets foo
/// <b>Setter should only be invoked by SomeClass</b>
/// </summary>
public Object Foo
{
get { return foo; }
set { foo = value; }
}
When you have some complex access or inheritance restriction, and enforcing it demands too much complexity in the code, sometimes the best way to do it is just properly commenting it.
Note however that you cannot rely on this if this restriction has some security implications, as you are depending on the goodwill of the developer that will use this code.
You cannot do that on that way, but you can access a property's setter method from a derived class, so you can use inheritance for the purpose. All you have to do is to place protected access modifier. If you try to do so, your colleague is right :). You can try doing it like this:
public string Name
{
get{ return _name; }
protected set { _name = value; }
}
keep in mind that the set method of the property is only accessible from the derived class.
Or you could have these two classes in an assembly alone and have the setter as internal. I would vote up for the design flaw though, unless the previous answer by milot (inheriting and protected) makes sense.
You could do:
public void setMyProperty(int value, Object caller)
{
if(caller is MyManagerClass)
{
MyProperty = value;
}
}
This would mean that you could use a 'this' pointer from the calling class. I would question the logic of what you're attempting to achieve, but without knowing the scenario I can't advise any futher. What I will say is this: if it is possible to refactor your code to make it clearer, then it is often worthwhile doing so.
But this is pretty messy and certinly NOT fool-proof ... you have been warned!
Alternativly...
You could pass a delegate from the Class with the Property (Class A) to the Manager Class (Class B). The delegate can refer to a private function within A to allow B to call that delegate as any normal function. This precludes that A knows about B and potentially that A is created before B. Again... messy and not fool-proof!
You can achieve to this by making a Public property in your "settable class" that will inherit from the real class that will have a protected property... this way only the inherit class can SET and not class that doesn't inherit. But the drawback is that you will require to have an inherit class...
Reflection, though I would agree that having to do this just to get around an access modifier is probably an indication of a bad design.
public class Widget
{
private int count;
public int Count
{
get { return this.count; }
private set { this.count = value; }
}
}
public static class WidgetManager
{
public static void CatastrophicErrorResetWidgetCount( Widget widget )
{
Type type = widget.GetType();
PropertyInfo info = type.GetProperty("Count",BindingFlags.Instance|BindingFlags.NonPublic);
info.SetValue(widget,0,null);
}
}
The reason this is a design flaw is because it seems muddled between the scope of the two objects.
The properties of a class should be accessible in the context of that class, at least internally.
It sounds like the settable property on your item class is really a property of the manager class.
You could do something similar to what you want by closely coupling the two classes:
public class MyItem {
internal MyItemManager manager { get;set; }
public string Property1 {
get { return manager.GetPropertyForItem( this ); }
}
}
Unfortunately this isn't great design either.
What your looking for is what C++ calls a Friend class but neither c# or vb has this functionality. There is a lot of debate as to the merit of such functionality since it almost encourages very strong coupling between classes. The only way you could implement this in c# would be with reflection.
If your goal is to have a class Foo let some property (e.g. Bar, of type Biz) to be changed by some other object, without exposing it publicly, a simple way to do that is to have an instance of Foo which is supposed to be changeable by some other object to pass that other object an Action<Biz> which points to a private method that changes Bar to the passed-in value. The other object may use that delegate to change the Bar value of the object that supplied it.
If one wishes to have give all instances of some type Woozle the ability to set the Bar value of any instance of Foo, rather than exposing such abilities on a per-instance basis, one may require that Woozle have a public static method Woozle.InstallFooBarSetter which takes a parameter of type Action<Foo, Biz> and one of type Object. Foo should then have a static method WoozleRequestBarSetter which takes an Object, and passes it to Woozle.InstallFooBarSetter along with an Action<Foo,Biz>. The class initializer for Woozle should generate a new Object, and pass it to Foo.RequestBarSetter; that will pass the object to Woozle.InstallFooBarSetter along with a delegate. Woozle can then confirm that the passed-in object is the one that it generated, and--if so--install the appropriate delegate. Doing things this way will ensure that nobody but Woozle can get the delegate (since the delegate is only passed to Woozle.InstallFooBarSetter), and Woozle can be sure its delegate comes from Foo (since nobody else would have access to the object that Woozle created, and Woozle.InstallFooBarSetter won't do anything without it).
if it is a design flaw depends on what you want to do. You could use the StackTrace class from System.Diagnostics to get the Type of the class setting your property and then compare to the type you want to allow setting yor property..but maybe there are better ways for performing something like this (e.g. boxing)