Declaring a value for an int as unchangeable - c#

Hey I want to have something like that
int a=0;
a=5(be unchangeable);
a=3;
Console.WriteLine(a);//which will print 5 and not 3
so basically make declare the variable a number and have it be final and unchangeable, I tried looking around but I only found things that work as the int is declared and not as a new value for it is declared.

doesn't this work?
const int a = 5;
see const(C# reference)

const int a = 0;
The const keyword is used to modify a declaration of a field or local
variable. It specifies that the value of the field or the local
variable is constant, which means it cannot be modified.
Ref.

You want the const keyword.
const int a = 5;
From MSDN:
The const keyword is used to modify a declaration of a field or local variable. It specifies that the value of the field or the local variable cannot be modified.
EDIT: Your requirement sounds odd and not useful. But if you really need it, you'll have to create a custom type. I'd suggest a class with a bool property stating whether or not it's mutable or not.
public class MyCustomInt
{
public bool IsMutable { get; set; }
private int _myInt;
public int MyInt
{
get
{
return _myInt;
}
set
{
if(IsMutable)
{
_myInt = value;
}
}
}
public MyCustomInt(int val)
{
MyInt = val;
IsMutable = true;
}
}
Then when you use it:
MyCustomInt a = new MyCustomInt(0);
a.MyInt = 5;
a.IsMutable = false;
a.MyInt = 3; //Won't change here!
Console.WriteLine(a); //Prints 5 and not 3
That's about as good as you can get, I think.

use readonly:
as it can be changed by the constructor but then not again.
public class MyClass {
private readonly int a = 0;
public MyClass(int a) {
this.a = a;
}
public void DoSomethingWithA() {
Console.WriteLine(this.a);
//a = 5 // don't try this at home kids
}
}
new MyClass(5).DoSomethingWithA();
A nice comparison between const and readonly

You can use a constant with the const keyword.
const int a = 5;
but if you do that, you will not be allowed to change to another value.
You also can check the use of the pointers:
int x = 5;
int y = 3;
int *ptr1 = &x; // point to x memory address
int *ptr2 = &y; // point to y memory address
Console.WriteLine(x); // print 5
Console.WriteLine(y); // print 3
Console.WriteLine((int)ptr1); // print 5
Console.WriteLine((int)ptr2); // print 3
Console.WriteLine(*ptr1); // print 5
Console.WriteLine(*ptr2); // print 3
* char identify a pointer and & specify the memory address. But you should take care with pointers because unlike reference types, pointer types are not tracked by the default garbage collection mechanism.

Related

How to fill a variable in class in array of classes?

I have a class with just one variable
public class C
{
int i;
}
And in another project file I create an array of classes
C[] classes = new C[100000];
So what i need to do to set some random value to the "i" variable in each class?
First you need to make C.i accessible. One way is to make C.i a public property. While you’re at it, public fields should be pascal cased and all identifiers should have meaningful names.
When naming public members of types, such as fields, properties, events, methods, and local functions, use pascal casing.
public class Foo {
public int Bar { get; set; }
}
Then you'd use System.Random. Instantiate it once and call Random.Next each time you want a random number.
using System;
var rand = new Random();
// int anyPositiveInt = rand.Next();
// int positiveIntLessThanFifteen = rand.Next(15);
// int intFromOneToFour = rand.Next(1, 5);
Finally, following the example in Creating N objects and adding them to a list, use System.Linq's Enumerable.Range, Enumerable.Select, and Enumerable.ToArray as follows:
Foo[] classes = Enumerable
.Range(0, 100000)
.Select(_ => new Foo { Bar = rand.Next() })
.ToArray();
If the requirement is to use a private field then I recant the earlier advice to make it a public property - properties might not have been taught yet
static void Main()
{
var r = new Random();
var maxValueOfI = 100;
var minValueOfI = -20;
var csArr = new C[100000];
for (var julius = 0; julius < csArr.Length; julius++) {
var brutus = r.Next(minValueOfI, maxValueOfI+1);
csArr[julius] = new C(brutus);
}
}
public class C
{
private int _i;
public C(int i){
_i = i;
}
}
So, what's going on here?
The main addition is a constructor to C. A constructor is a special method that is called by C# when a new object is constructed. Every class has one even if you can't see it (the compiler provides one if you don't). Constructors are methods that are intended to ensure the class is fully set up and ready to use. Because it's inside the class it has full access to all the data fields of the class:
public C(int i){
_i = i;
}
This constructor takes an int, and sets the private field _i to the value of the passed in number. It's quite common to use this naming pattern for fields (prefix with underscore) and it helps avoid a name collision with the arguments to the method (in this case called i). If they had both been called i the class one would have to be prefixed with this. and it's (IMHO) more clutter
This line of code calls the constructor:
csArr[julius] = new C(brutus);
We've previously calculated a random number between -30 and 100 (inclusive both ends) and stashed it in a variable called brutus. This number is passed to the constructor, which is called when we say new C. The resulting fully constructed C instance is stored in one of the array slots
try this
static void Main()
{
Random rand = new Random();
var max=100000;
C[] array = new C[max];
for (var i=0; i <max; i++)
array[i] = new C { Num = rand.Next(0, max)};
// or using a constructor
array[i] = new C (rand.Next(0, max));
}
public class C
{
public int Num {get; set;}
public C (int num)
{
Num=num;
}
public C (){}
}
First of all, in your current code i is a private field. Let's add a constructor to set this field:
public class C {
int i;
public C(int value) {
i = value;
}
}
Then you can try using Linq:
using System.Linq;
...
Random rand = new Random();
...
C[] classes = Enumerable
.Range(0, 100000)
.Select(i => new C(rand.Next(0, 100))) //TODO: Put the right range here
.ToArray();

Custom auto properties in C# [duplicate]

This question already has answers here:
C# 3.0 Auto-Properties - Is it possible to add custom behaviour?
(6 answers)
Closed 1 year ago.
I have the following class with auto properties:
class Coordinates
{
public Coordinates(int x, int y)
{
X = x * 10;
Y = y * 10;
}
public int X { get; set; }
public int Y { get; set; }
}
As you can see from the constructor I need the value to be multiplied by 10.
Is there anyway to do it without removing autoproperties?
I tried the following not thinking that it causes recursion and then everything goes fubar
public int X { get {return X;} set{ X *= 10;} }
I would like to assign values to X and Y multiplied by 10.
Coordinates coords = new Coordinates(5, 6); // coords.X = 50 coords.Y = 60
coords.X = 7; // this gives 7 to X but I would like it to be 70.
In order to make setter working like that, you'll need to use backing field:
class Coordinates
{
public Coordinates(int x, int y)
{
X = x;
Y = y;
}
private int _x;
public int X
{
get { return _x; }
set { _x = value * 10; }
}
private int _y;
public int Y
{
get { return _y; }
set { _y = value * 10; }
}
}
Given your example:
Coordinates coords = new Coordinates(5, 6); // coords.X = 50 coords.Y = 60
coords.X = 7; // this gives 70
However, I don't recommend you having such setter because it could lead to confusion. It's better to have a dedicated method which will do such multiplication. In the end, your code will be more descriptive and intuitive.
You get a recursion, because you again call the same property, which in turn calls the same property, which in turn calls the same property... you get the point.
public int X { get {return X;} set{ X *= 10;} }
How does auto properties works ?
Behind the scenes Properties are actually methods, which means they don't actually store data. So who saves the data ? AutoProperties generate private backend field to save the data.
So in the simple declaration of auto property
int X { get; set; }
The compiler translate it into something like that
private int <X>k__BackingField;
public int X
{
[CompilerGenerated]
get
{
return <X>k__BackingField;
}
[CompilerGenerated]
set
{
<X>k__BackingField = value;
}
}
So no matter if you use it as Auto Properties or simple property, they are the same.
Now, to answer you question, with paraphrasing, "How do i return the value multiply with 10"
You can solve it with using 2 ways:
1. By saving the data multiply by 10 (setter implementation)
2. By returning the data multiply by 10 (getter implementation)
I won't elavorate, which one you should use, because for this kind of simple scenario, both will be perfectly valid.
I would just say that some of the factors for the choice will be micro(micro micro micro) performence, true state storage.
Here is the setter implementation
private int _x;
public int X
{
get
{
return _x;
}
set
{
return _x*10;
}
}

reference and value types c#

I am learning C# memory management and faced weird to me thing.
I dynamically allocate memory for Student object and change it in a method — it is being changed.
I dynamically allocate memory for int object and change it in a method — it isn't being changed.
Why??
class Student
{
public int id;
public string name;
}
class Program
{
static void Main(string[] args)
{
Student s1 = new Student();
s1.id = 5;
s1.name = "myname";
ChangeStud(s1);
Console.WriteLine(s1.id);
Console.WriteLine(s1.name);
int x = new int();
x = 2;
ChangeInt(x);
Console.WriteLine(x);
}
static void ChangeStud(Student s)
{
s.id = 500;
s.name = "changedname";
}
static void ChangeInt(int x)
{
x = 500;
}
}
The output is:
500changedname2
Passing a class object by value is similar to passing a pointer to a data structure in a non-object-oriented language, because what is actually passed is the memory location of the object. Since that address is given, the memory to which the address refers can be modified.
Passing a scalar variable value such as an integer is just passing a value. The called method doesn't receive the memory location of the int, just a copy of the value. Any changes will not modify the value in the original memory location.
The problem is that you are changing the int in the ChangeInt method but the parameter is copied not referenced you can either use the ref keyword or return the value of the method:
static void ChangeInt(ref int x)
{
x = 500;
}
or
static int ChangeInt(int x)
{
return 500;
}
If you use the later method remember to catch the value

C# constructors with parameters - passing on

I got a question about constructors for my Windows Forms Application. First of all I want to say that I am new to programming.
The thing is this. I am making a constructor in another class that should hold different parameter values. In this case it should be int X, int Y, int Length, int Height. What I want to do here is to make the X, Y, Length and Height all random for my picturebox. I send code down below:
class Rechthoekcs
{
Random random = new Random();
public int Xas
{
get;
set;
}
public int Yas
{
get;
set;
}
public int Lengte
{
get;
set;
}
public int Breedte
{
get;
set;
}
public Rechthoekcs(int x, int y, int lengte, int breedte)
{
this.Xas = x;
this.Yas = y;
this.Lengte = lengte;
this.Breedte = breedte;
x = random.Next(x);
y = random.Next(y);
lengte = random.Next(lengte);
breedte = random.Next(breedte);
}
From my Form1 I want to call this class/constructor
But it gives me an error. It says "Does not contain a constructor with 0 arguments" and I know that because I typed the x, y, length and width. But I cannot add just the variables from the other class into the new parameter. I really don't get it. I find constructors very hard. I never know what parameters I should give with it...
I send the code down below from my Form1:
public partial class Form1 : Form
{
Rechthoekcs Rechthoek = new Rechthoekcs(.......);
public Form1()
{
InitializeComponent();
}
It it really frustrating for me. I tried looking up on the web and books and such but all the explanation about which parameters should be given for a constructor is not clear to me. Could someone explain this? Not understanding it drives me insane. Plus I am getting often stuck at these points..
public Rechthoekcs(int x, int y, int lengte, int breedte)
{
this.Xas = x;
this.Yas = y;
this.Lengte = lengte;
this.Breedte = breedte;
x = random.Next(x);
y = random.Next(y);
lengte = random.Next(lengte);
breedte = random.Next(breedte);
}
You are assigning the values of the parameters to your private Data Members before you do anything "randomizing" about them. You are simply changing the values of the parameters in your constructor without assigning them. Swap the order you do them in.
public Rechthoekcs(int x, int y, int lengte, int breedte)
{
x = random.Next(x);
y = random.Next(y);
lengte = random.Next(lengte);
breedte = random.Next(breedte);
this.Xas = x;
this.Yas = y;
this.Lengte = lengte;
this.Breedte = breedte;
}
Now you have successfully randomized your values that will be set to your data member variables ASSUMING that those variable you put in there actually exist, which they should. Better/more modular code would do this randomization where you create your object.
Ex: Object foo = new Object(new Random, new Random, new Random, new Random)
Not the answer OP is looking for, but this is how you solve "I don't yet know the value but I need to construct object anyway" version of the question.
You can delay requesting the data by passing Func<T> for each parameter instead of just T assuming the values actually will be available by the time they needed:
class UseDelayedValues
{
Func<int> x;
public UseDelayedValues(Func<int> x)
{
this.x = x;
}
public UseWithX(int other)
{
return other + x();
}
}
int value = 0;
var r = new UseDelayedValues(() => value);
value = 42;// get some value
Console.WriteLine(r.UseDelayedValues(1));
var delayedFromTextbox = new UseDelayedValues(() => int.Parse(textBox1.Value));
Lines using the UseDelayedValues can be spread over time. I.e. instance constructed in constructor, but value used only when form is shown by button click.

Property by ref C# (many parameters)

chaps/chapettes, I understand there are questions related to this but this is somewhat different - all related questions I could find only used one parameter as an example. Anyways, to the point:
This year, I have converted source code written in Delphi to C#. Beyond this, the scope of my tasks has been to optimize and generally improve the code base. The source code has been written by a handful of individuals, each with no knowledge or experience of software engineering principles or techniques - so some of the code is abismal.
Anyhow, perhaps someone can provide a suggestion/solution to my quarrels:
Currently, in C# have a class for storing 9 values:
class StoreStruct
{
int A1 { get; set;}
int B1 { get; set;}
int C1 { get; set;}
int A2 { get; set;}
int B2 { get; set;}
int C2 { get; set;}
int A3 { get; set;}
int B3 { get; set;}
int C3 { get; set;}
}
Now what I have an issue with is that, ideally, I would like to pass the properties of this class into methods by ref. However, I know I can't do this. Instead the source code works by creating temp local variables, passes these by ref and then assigns the class properties to these values. This can be seen as follows:
private void MethodA()
{
var temp = new StoreStruct();
var a1 = 0;
var b1 = 0;
var c1 = 0;
var a2 = 0;
var b2 = 0;
var c2 = 0;
var a3 = 0;
var b3 = 0;
var c3 = 0;
if (expression1)
{
MethodB(ref a1, ref b1, ref c1, 1, 1);
temp.A1 = a1;
temp.B1 = b1;
temp.C1 = c1;
}
if (expression2)
{
MethodB(ref a2, ref b2, ref c2, 2, 2);
temp.A2 = a2;
temp.B2 = b2;
temp.C2 = c2;
}
if (expression3)
{
MethodB(ref a3, ref b3, ref c3, 3, 3);
temp.A3 = a3;
temp.B3 = b3;
temp.C3 = c3;
}
}
private void MethodB(ref int a, ref int b, ref int c, int num1, int num2)
{
a = num1 + num2;
b = num1 - num2;
c = num1 * num2;
}
What I would like to do in an ideal world:
MethodB(ref temp.A1, ref temp.B1, ref temp.C1, 1, 1);
From looking at other posts, I understand why this isn't catered for in C# and quite frankly I agree with the reasoning behind it. I have seen a few workarounds and a few suggestions in other posts but these only relate to an example with one method call and only one parameter being passed by ref. Does anyone have an elegant solution that would allow me to update the class properties in MethodB without having to pass temporary variables?
Just remove getters and setters from StoreStruct.
Personally I would use the workaround you did in your question. However if you really want it you would need to pass delegates in to the function that would assign the values for you then call them inside your function.
if (expression1)
{
MethodB((a) => temp1.A1 = a,
(b) => temp1.B1 = b,
(c) => temp1.C1 = c,
1, 1);
}
private void MethodB(Func<int> setA,
Func<int> setB,
Func<int> setC,
int num1, int num2)
{
setA(num1 + num2);
setB(num1 - num2);
setC(num1 * num2);
}
Properties are nothing but syntactic sugar for getter and setter function calls, which is why you cannot pass them by reference. In general in C# if you're using ref parameters, you're probably doing it wrong.
Simply pass the StoreStruct object, and let the function set the properties. A class is a reference type, so essentially all objects are passed "by reference" by default in C#.
I think modifying your StoreStruct will help with this, and eliminate a bunch of madness:
class Thing {
int A { get; set; }
int B { get; set; }
int C { get; set; }
}
class StoreStruct { // Not actually a struct!
public readonly Thing thing1;
public readonly Thing thing2;
public readonly Thing thing3;
}
Use:
private void MethodA()
{
var temp = new StoreStruct();
if (expression1)
{
MethodB(temp.thing1, 1, 1);
}
if (expression2)
{
MethodB(temp.thing2, 1, 1);
}
if (expression3)
{
MethodB(temp.thing3, 1, 1);
}
}
private void MethodB(Thing thing, int num1, int num2)
{
thing.A = num1 + num2;
thing.B = num1 - num2;
thing.C = num1 * num2;
}
Well, if it were me the first thing I'd do is try to get some real names here. What's an A1, B2, etc? Is it a cash register? A puppy? A space sled? Names should reflect what's going on. Next, ideally classes should modify their own data as much as possible, so I would tend to think in terms of passing the object and calling as few methods as possible on the object to do whatever modifications are needed rather than passing around a set of flags, especially if the latter have really obtuse names. Sorry if that seems like more of a general criticism, but it goes to what you mentioned about being tasked to improve the code base over time. (If they're really structs, I've always found properties to be overkill except insofar as they might aid debugging).
It seems that you are having three sets of values in your class. If you make a class of such a set, you can have three values in the class:
class ABC {
int A { get; set; }
int B { get; set; }
int C { get; set; }
}
class StoreStruct {
ABC ABC1 { get; set; }
ABC ABC2 { get; set; }
ABC ABC3 { get; set; }
public StoreStruct {
ABC1 = new ABC();
ABC2 = new ABC();
ABC3 = new ABC();
}
}
Now you can pass an ABC value into MethodB, and as that is a changeable set of values, you don't even need the ref keyword for the parameter:
private void MethodB(ABC abc, int num1, int num2) {
abc.A = num1 + num2;
abc.B = num1 - num2;
abc.C = num1 * num2;
}
Call:
MethodB(temp.ABC1, 1, 1);
You could also make MethodB a member of the class ABC, so that you don't pass the value to the method, you call the method on the value:
class ABC {
int A { get; set; }
int B { get; set; }
int C { get; set; }
public void MethodB(int num1, int num2) {
A = num1 + num2;
B = num1 - num2;
C = num1 * num2;
}
}
Usage:
temp.ABC1.MethodB(1, 1);
I agree with Jonathan's comment that you're probably doing something wrong and could encapsulate your state in a way that doesn't require passing by ref.
In order to do what you want, you can use a backing variable for the getters/setters.
private int _a1;
public int A1
{
get
{
return _a1;
}
set
{
_a1 = value;
}
}
public void Foo()
{
Bar(ref _a1);
}
It looks like you want to exchange every Property of a class. In the OOP-world the best way to do this is to send the complete class to the method, not just the properties:
public void MethodB(ref StoreStruct store) {
// store.A1=[...];
}
Wow, lots of answers to this question already. Well, here's another. You could try creating a class that can act as a reference to an integer like this:
class IntRef
{
private int value;
public IntRef(int value)
{
this.value = value;
}
public static implicit operator IntRef(int value)
{
return new IntRef(value);
}
public static implicit operator int(IntRef value)
{
return value.value;
}
}
Then change your int declarations and your ref int paremeters to IntRef.
Be aware that if you do this, though, that your set procedure may not run. You may have to move some of that code into the IntRef class or raise an event from IntRef so that the StoreStruct can react to the changed value.

Categories