C# Public variables in a class - c#

I have a class which has a 2D jagged array declared in it's constructor, and in that class I have two methods called GetXY and SetXY, that modify said array.
However, I am unsure whether I should use these methods or in fact declare the grid as public, meaning there would be 2 ways of setting and reading values in the array, like this:
ProceduralGrid pg = new ProceduralGrid(10, 10);
pg.grid[0][0] = 2;
pg.SetXY(0, 0, 2);
Which one shall I use, and why?

Why not use
public T this[int x, int y]
{
get
{
return grid[x][y];
}
set
{
grid[x][y] = value;
}
}
Naturally check for valid x and y etc...

Use methods to access the array. Either SetXY or an indexer as suggested be Alessandro. That way, you can later change the implementation without changing your class interface.

It is best to use methods to set variables that are used inernally.
This way you can protect your inner object and are free to implement extra validation or modify the object as required.
This allows you to easily change the behaviour of that object later on.

Related

Intellisense - can it get a hint to look at a range of consts?

If I have a method parameter that is an enum, intellisense will pick up the possible values for this enum and let me pick one. This isn't ideal for me however as it's possible people might want to use values outside of my defined set. If I make my argument a byte instead, I can then create a static class filled with consts that hold my defined set of values - the only downside is that intellisense does not know about this library of values. Is there a way to point intellisense towards a range of 'helper' values?
Technically you can assign 'invalid' values to your enum. Since the backing store of an enum is an int, you can assign any value to it:
public enum X
{
A = 0,
B = 1
}
class Program
{
static void Main(string[] args)
{
X x = (X)2;
}
}
That way, you can still have the IntelliSense support, and allow off-values. Of course, this has drawbacks too, so you have to consider whether they outweigh the pros.
A fix for that could be to assign 'custom' values in your enum, which you reserve for use later on:
public enum X
{
A = 0,
B = 1,
Custom1 = 2
}
To directly answer the Intellisense part of you question, then no I don't think it is possible to do that.
However I think you can solve your problem by using function overloading, this way you can use either type and have the benefits of both:
void Myfunction(MyEnum e)
{
MyFunction((byte)e);
}
void MyFunction(byte b)
{
// Do something
}

Advantages of indexers over object array?

I read about indexers in MSDN - Indexers which explains how we can use objects like array with index i.e. just like normal Array. However, I think we can create array of objects like
point[] array = new point[100];
So what is the special advantages Indexer over object array?
If all you are after is a collection of objects then an indexer has absolutely no benefit over an array. However, if you need to store state as well as a collection, that's where an indexer shines.
For example, consider the following
public class Tree
{
private Branch[] branches = new Branch[100];
...
public string Name { get; set; }
public Branch this[int i]
{
get
{
return branches[i];
}
}
}
Tree holds an internal collection but also has state of it's own. Having an indexer property allows for simple access to the underlying collection e.g.
tree.Name = "Tree";
var branch = tree[0];
Not in this case that you have mentioned above. However, if you have anything that cannot be represented as an array will be a good example for Indexers to be used.
One .Net framework example is Dictionary. If you see the definition of Dictionary type in .Net you will find that they let you get an access of value through key. So that is a good example of using indexers where the index is presented as string.
Without indexers, how would you do that? of course by index value but it cannot be of type string then, will that be user friendly? I guess not!
So indexers gives you an opportunity to represent your code well.
Similarly, in case of point type, of course you can access the value of by index i.e. 0,1,2...99. What if you want to make more user friendly, such as point["x"]. That is where Indexers will help you.
Another example I could think of how about if you want to access your stack like s1 instead of push and s[0] instead of pop method.
There is a very good example of indexers by Microsoft where you can access file byte by byte by providing character location as index.
http://msdn.microsoft.com/en-us/library/aa288465(v=vs.71).aspx
In your line of code, you've defined an array of point objects, whatever those might be.
point[] array = new point[100];
Assuming you have direct access to the array, you can access the first element in your array like this:
var firstPoint = array[0];
The page you linked to is showing you how you could access that array, if it were defined inside your class, and you didn't have direct access to the array (since it's private).
For example, we could modify the example on that page to use your array:
class SampleCollection
{
private Point[] arr = new Point[100];
public Point this[int i]
{
get { return arr[i]; }
set { arr[i] = value; }
}
}
Then you could access the first element in the array like this:
var sc = new SampleCollection();
var item1 = sc[0];
That isn't an indexer.
An indexer is not used to create an array of objects, it is actually an operator overload to the '[]' operator.
An example for it's use would be if you wanted to make a List wrapper class.
In order to preserve the square braces functionality you would need (and want) to override the square braces operator. This is done via an indexer method.

Passing a value by reference to List.Add()

How could I pass a value by reference to the List?
int x = 2;
List<int> newList = new List<int>();
newList.Add(x);
System.Console.WriteLine(x);
x = 7;
System.Console.WriteLine(newList[0]);
newList[0] = 10;
System.Console.WriteLine(x);
My objective is elements on the list to be related with the previous ones. In C++ I would use a list of pointers, however right now I feel hopeless.
You can't do it with value types.You need to use a reference type.
(change) You can't do it with object too, you need to define your custom class which has a int property. If you use object it will be automatically perform boxing and unboxing.And actual value never affected.
I mean something like this:
MyInteger x = new MyInteger(2);
List<MyInteger> newList = new List<MyInteger>();
newList.Add(x);
Console.WriteLine(x.Value);
x.Value = 7;
Console.WriteLine(newList[0].Value);
newList[0].Value = 10;
Console.WriteLine(x.Value);
class MyInteger
{
public MyInteger(int value)
{
Value = value;
}
public int Value { get; set; }
}
ints are primitives, so you are not passing around a pointer,but the value it self.
Pointers are implicit in C#,so you can wrap ints in an object and pass that object around instead and you will be passing a pointer to the object.
You can't store value types in a .NET generic collection and access them by reference. What you could do is what Simon Whitehead suggested.
I see few solutions of this problem:
1) Create a class which will hold the integer (and possibly other values you might need)
2) Write "unsafe" code. .NET allows usage of pointers if you enable this for your project. This might even require creating custom collection classes.
3) Restructure your algorithm to not require references. E.g. save indexes of values you wish to change.

How can I get the default value of a field in a class in C#?

Say I have my class, and I have the non-static variable
int x = 5;
After the code runs x is changed to something else, how can I get the value x started with using reflection?
Short answer: you can't.
If you implement some kind of custom transactional system, than it is possible. Out of the box: no luck.
And yes, the custom transactional system can be very simple: add another field or property that you use to 'remember' the initial value.
if i understand you correctly you want the initial value of the x.
for that you need another member or parameter to keep the first initializing of x. for example in your class:
int FirstX = -1;// or any other value you know ain't gonna come
bool firstInitial = true;
public int X
{
set
{
if(firstInitial)
{
FirstX = value;
firstInitial = false;
}
x = value
}
}
Now if you mean default value that is set at class level, you already know as it is constant other way would be creating an instance of the class for which you need default value.
ClassName className= new ClassName();
className.MyProp//This will always give default value.
new ClassName().MyProp //would also do.
If you want list of transactional values you need to implement it, reflection is not meant for that.

Is this a good practice of immutability?

Good morning,
Suppose I have a class
public class Class
{
int something;
int[] otherThing;
}
and I want to make objects of type Class immutable. Suppose also that I have a very frequent operation which creates a new object of type Class,
public Class SomeFunction()
{
int[] Temp = new int[] { ... };
return new Class(1, Temp);
}
To avoid creating new objects too often, and since Tempis no longer accessible out of the method, is it too bad to set on the constructor
this.otherThing = Temp;
instead of
otherThing = new uint[Temp.Length];
for (int i = 0; i < Temp.Length; i++)
{
this.otherThing[i] = Temp[i];
}
?
Thank you very much.
If the constructor that does this is private its fine IMO. Since you know the content of the other array will never change you can directly use it. You could even share one instance of the array between several instances of your class if you want to without causing any problems.
A public constructor directly using a provided array is a bad idea on the other hand. Since that can be used to break immutability.
It is better to assign a copy of temp to otherThing so that any changes to otherThing will not change temp. You can also use the Array.CopyTo method for this purpose.
In addition you should seriously consider using IEnumerable<int> or IList<int> instead of int[] because arrays by nature work against the idea of immutability. Read this blog post by Eric Lippert.
The difference is that in the first option you always get a new instance and in the second one all the created "Class"es will point to the same array (!). So if you change something in the array in any Class, all the other classes are changed.

Categories