i have the following array :
int[] myArray = {21,21,364,658,87};
and a reference to the second element like so:
int rr = myArray[1];
i want something like :
rr = 500
Console.writeLine(myArray[1]);// ---> should print 500 !
i hope you guys got my idea , i can do this easily in python like the example above.
so
how to do this in C#
my solution would probably be create property with arr[1] as its backing property
something like:
public int rr
{
set{ arr[1] = value;}
get{ return arr[1];}
}
and than rr=500; will be the same as arr[1]=500;
You could use something like this:
public static class ArrayExtensions
{
public static Action<int> CreateSetter(this int[] array, int index)
{
return (value) => array[index] = value;
}
}
[TestFixture]
public class ArrayTest
{
[Test]
public void Test()
{
int[] myArray = {21,21,364,658,87};
Action<int> rr = myArray.CreateSetter(1);
rr(500);
Assert.AreEqual(500, myArray[1]);
}
}
When you do this:
int[] myArray = {21,21,364,658,87};
int rr = myArray[1];
rr = 500;
You will only overwrite the value in rr, there is no way for you to get the actual memory address of an arrays inner elements, and thereby updating it.
My answer must therefore be:
myArray[1] = 500;
I'm trying to understand what you're trying to do, if you want to encapsulate your change in a function you could pass the reference on this way, but it's all about what you want to do with it:
public void Proc()
{
var ints = new [] { 1, 2, 3, 4 };
FunctionChangingByReference(ref ints[1]);
}
public void FunctionChangingByReference(ref int x)
{
x = 500;
}
In C# there are no pointers, only references.
(I'm lying a bit, you could use pointers if you create a unsafe context, but we don't do that in C#, and neither should you. When we code C++ we do, but that's C++, and we do it at a cost, we make the code a bit more fragile and error prone. When I code C# I try to optimize the code on a higher level than memory address shuffling. If you really need to optimize on that level you should write the code in C++ and import that code as a dll, then you have a good separation of concern, and don't forget to test drive the development!)
Simply myArray[1] = 500! You could use a property as Nahum Litvin has suggested if you specifically want a reference to a specific integer within the array.
#des answer has awaken my interest. So I tried his solution and it works as expected:
int[] numbers = new[] { 1, 2, 3 };
fixed (int* number = &numbers[0])
{
*number = 10;
}
Console.WriteLine(String.Join(", ", numbers)); // Outputs "10, 2, 3"
You have to compile it with the /unsafe option.
I hope you see that this may bring some problems.
Therefore I don't recommend this solution.
What you want is a basically pointer to a variable.
It's hard to explain the difference between "value type" (like int or struct), a reference and a pointer. I can only recommend learning C.
Here's solution that works, although it may need a lot of changes to your code.
//a class that will hold an int inside
public class myIntWrapper
{
//this is the value wrapper holds
public int theValue;
//constructor taking the value
public myIntWrapper(int argument)
{
theValue = argument;
}
//operator to convert an int into brand-new myIntWrapper class
public static implicit operator myIntWrapper(int argument)
{
return new myIntWrapper(argument);
}
//operator to convert a myIntWrapper class into an int
public static implicit operator int(myIntWrapper wrapper)
{
return wrapper.theValue;
}
}
now you can write:
//create an array -
//setting values to every item in array works
//thanks to operator myIntWrapper(int argument)
myIntWrapper[] myArray = new myIntWrapper[5]{1,2,3,4,5};
//now take a "reference"
myIntWrapper rr = myArray[1];
//change the value
rr.theValue = 500;
//from now on myArray[1].theValue is 500;
//thanks to operator int(myIntWrapper wrapper)
//you can write:
int ss = rr;//it works!
please remember to never do:
rr = 600;
because this will actually create brand new myIntWrapper, that's not "connected" anywhere.
So remember:
rr.theValue = 500;//this changes the value somewhere
rr = myArray[3];//this changes where rr is "pointing" to
Yes, it's quite complicated but I doubt it can be done any simpler without unsafe code. I'm sorry for not explaining it more. I'll answer to all questions in comments.
Related
The following code doesn't update the copy of a inside the array.
int a = null;
int[] numbers = new int[1];
numbers[0] = a;
a = 5; // 5
Console.WriteLine(numbers[0]); // null
Got a programming task requiring to set-up a structure of locations linked by portals between them which isn't possible by just listing the required connections. I'll get references to null that stay null even if I fill an entity later in the code.
Looking for keywords or techniques which might solve my issue.
You could have reference types instead of value types inside array, therefore updating the value of the inner object will also affect the array.
var tab = new MyClass[1];
var obj = new MyClass(5);
tab[0] = obj;
Console.WriteLine(tab[0].Value); // 5
tab[0].Value = 10;
Console.WriteLine(tab[0].Value); // 10
obj.Value = 15;
Console.WriteLine(tab[0].Value); // 15
public class MyClass
{
public MyClass(int value)
{
Value = value;
}
public int Value { get; set; }
}
integers is a value type, as such the actual value is copied. So there is never any 'instance' in your example code, only copies of the value.
You should probably wrap your value in a class, since classes are a reference type to get your desired behavior. This might be useful when you need to share some mutable between multiple components. You can also add an event that is raised whenever the value is changed to let any component that needs the value know that it might need to update something. For example:
public class MyChangeable<T>
{
private T value;
public MyChangeable(T value) => this.value = value;
public T Value
{
get => value;
set
{
this.value = value;
OnChanged(this, value);
}
}
public event EventHandler<T> OnChanged;
}
There is also ref return and ref locals that could do something like your example, but this is mostly intended to get better performance by avoiding copies of large structs, it is not as useful if you want to share values between components.
Arrays are reference types
var a = new int[1];
var numbers = new [] { a };
a[0] = 5;
Console.WriteLine(numbers[0][0]);
You just have to remember that you're one level deeper than you wanted to be/you need to stick a [0] on everything you wouldn't have stuck it on before. It's a bit of a hack, and I'd probably make a class for it like other answers recommend, but stuffing a value type in an array of size 1 can be a useful technique to quickly get reference type behavior out of a value type
ref locals may help you in your task, even if they have strict limitations due to the lifetime of the involved objects, so they could be not applicable as a general solution.
A small example based on your question can be as follows:
int[] array = new int[1];
ref int elem = ref array[0];
elem = 5;
Console.WriteLine(array[0]); // 5
This works not only with value types (including nullable types) but also with reference types.
I'm making a C# script in Unity. My intention is to create a class Scenario, create classes representing different scenarios, which would then be stored in an array scenarioListAll.
A (simplified) version of the code is as follows:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class OverallManager2 : MonoBehaviour
{
public static object[] scenarioListAll = new object[40];
public class Scenario
{
public string scenarioDesc;
public bool surprise; // The 'surprise' bool I want to reference is defined here
public string surpriseType;
public int[] leftOption;
public int[] rightOption;
public int scenarioNumber;
public Scenario(string st, bool sp, int[] l, int[] r, int n)
{
scenarioDesc = st;
surprise = sp;
leftOption = l;
rightOption = r;
scenarioNumber = n;
}
// I haven't used this, but I'm not sure if this matters so I'm including this too
public Scenario(string st, bool sp, string spt, int[] l, int[] r, int n)
{
scenarioDesc = st;
surprise = sp;
surpriseType = spt;
leftOption = l;
rightOption = r;
scenarioNumber = n;
}
}
public static int[] getArray(int a, int b, int c, int d, int e, int f)
{
int[] arr = new int[6] {a, b, c, d, e, f};
return arr;
}
// Storing scenarios, am looking for the bool (2nd position)
public Scenario s1 = new Scenario("Test1", false, getArray(1, 1, 1, 1, 1, 1), getArray(1, 1, 1, 1, 1, 1), 1);
public Scenario s2 = new Scenario("Test2", true, getArray(1, 1, 1, 1, 1, 1), getArray(1, 1, 1, 1, 1, 1), 2);
public Scenario s3 = new Scenario("Test3", false, getArray(1, 1, 1, 1, 1, 1), getArray(1, 1, 1, 1, 1, 1), 3);
void Awake()
{
// Store scenarios in object array
scenarioListAll[0] = s1;
scenarioListAll[1] = s2;
scenarioListAll[2] = s3;
for(int i = 0; i < 40; i++)
{
object temp = scenarioListAll[i]; // Trying to extract the object stored in the array in a temp object
bool surpriseCheck = temp.surprise; // I am having problems with this line
if(surpriseCheck == true)
{
// Do something
}
}
}
// Ignoring start and update since they're irrelevant in this context
}
What I would like to do is to check whether the surprise element within a newly defined scenario (e.g. s1) is true. To do that, I was planning to extract the scenario stored in the array scenarioListAll, and then extract the surprise component from there. However, I'm couldn't figure out how to do this (e.g. in the code shown above, it returns Compiler Error CS1061).
I don't think I was able to find any documentation on this either, but I might not have understood something. I'm learning on my own so please bear with my poor knowledge/presentation.
Thank you for your time. Your help is much appreciated.
You are having a compilation issue due to the fact that the c# compiler doesn't know that temp is a Scenario since you declared it as "object". If you want to loop through the scenarios and check to see if they are a surprise you can use something like this:
foreach(Scenario temp in scenarioListAll)
{
bool surpriseCheck = temp.surprise;
if(surpriseCheck == true)
{
// Do something
}
}
Another way of accomplishing the same task with more control over the iteration would be:
for(int i = 0; i < scenarioListAll.Length; i++)
{
Scenario temp = scenarioListAll[i];
bool surpriseCheck = temp.surprise;
if(surpriseCheck == true)
{
// Do something
}
}
The benefit of the first version is that you don't have to worry about overrunning the bounds of the array. As Mike added below you could also use var to have the compiler fill in the type for you.
It's sometimes easiest to allow the compiler to determine the type of a variable for us.
In your case, you've specified that the variable temp will be of type object. Now, that's fine, but while a Scenario derives from object, and object is the lowest level class in the .Net environment, and is not a Scenario.
The var keyword doesn't mean that the declared type is of a "variable" type, instead it's telling the compiler just to "fill in" the correct type, based on the action you're taking. So, to put this in to action in your case, you could do this instead:
for( var i = 0; i < 40; i++ ) // notice the use of var here as well
{
var scenario = scenarioListAll[i]; // renamed temp to scenario
// var surpriseCheck = scenario .surprise; // var used but line not required
if( scenario.surprise )
{
// Do something
}
}
I went overboard there to demonstrate that the compiler is quite happy with the var keyword just about wherever you'd specify a data type as a type for a variable. Obviously not when you're trying to cast types, and there ARE sometimes where you'd want to specify the exact type you're trying to instantiate.
In your case, your next issue will be that you've defined the array as having 40 object elements, but you've then only instantiated 3 Scenario elements (which is valid, but probably not quite what you want overall). So your code, as it stands, is going to NullReference error out. You'll be able to avoid that, with a small modification, so your amended code could look like this, to include some type checks:
for( var i = 0; i < scenarioListAll.Length; i++ )
{
// First, check to see if the object in the array cell is a Scenario.
// If the item in the cell is a Scenario, check to see if surprise is set.
if ( scenarioListAll[i] is Scenario scenario && scenario.surprise )
{
// Do something
}
}
for more information on the is keyword, check the Microsoft Docs here.
This is my first question on the site and I am sure I'll find my answer here.
For school, I was trying to do some basic C# coding for a challenge that was given to us.
Here is the problem:
Normally when I pass a value through a method I don't run into issues. Like so:
static void Main(string[] args)
{
// Declare Integer
int originalInt = 20;
// Call the Method
int multipliedInt = Multiplication(originalInt);
// Prompt
Console.WriteLine("Original: {0} Modified: {1}", originalInt, multipliedInt);
}
// Method
static public int Multiplication(int original)
{
// Quik Maffs
int modifiedValue = original * 2;
return modifiedValue;
}
The above example works just fine. The original value is 20 and the modified value is 40.
However, this changes when I attempt to do that with an array:
static void Main(string[] args)
{
// Declare Original Array
int[] originalArray = new int[] {1, 4, 6, 8, 12};
// Call Method
int[] multipliedArray = Multiplication(originalArray);
// Prompt
Console.WriteLine("Original: [{0}], Multiplied: [{1}]", String.Join(", ", originalArray), String.Join(", ", multipliedArray));
}
// Method
static public int[] Multiplication(int[] original)
{
// New Int
int[] modified = original;
// Loop
for (int i = 0; i < modified.Length; i++)
{
modified[i] *= 2;
}
return modified;
}
The code above returned the modified value twice. It seems like it modifies the original value as well.
Any idea why this is happening?
int is a value type. When you pass a value type to a method, you pass a copy of the value.
Arrays are reference types. When you pass a reference type to a method, you pass a copy of the reference... but both the copy and original still refer to the same object.
Now it seems you may have understood this much, because of this code:
(This is why I re-opened the question... the stock ref-vs-value answer wasn't gonna cut it here)
int[] modified = original;
However, the other thing that happens with reference types is assignments also only copy the reference. So modified and original in that snippet again refer to the same array object.
To fix this, you need to make an actual deep copy of the array. There are several ways to do this. I would tend to write the method this way:
static public IEnumerable<int> Multiplication(IEnumerable<int> original)
{
return original.Select(i => i * 2);
}
...and append a .ToArray() at the end of the method call if and only if I really need a full array (hint: very often it turns out you don't), like this:
int[] multipliedArray = Multiplication(originalArray).ToArray();
or like this:
var multipliedArray = Multiplication(originalArray);
But I understand there are a number of things here that aren't very familiar to a beginner. You might try something more like this:
static public int[] Multiplication(int[] original)
{
int[] modifed = new int[original.Length];
for (int i = 0; i < original.Length; i++)
{
modified[i] = original[i] * 2;
}
return modified;
}
I'm coming from a C++ background. This question has been asked before, but try as I might I cannot find the answer. Let's say I have:
string[] ArrayOfReallyVeryLongStringNames = new string[500];
ArrayOfReallyVeryLongStringNames[439] = "Hello world!";
Can I create a string that references the above (neither of these will compile):
string a = ref ArrayOfReallyVeryLongStringNames[439]; // no compile
string a = &ArrayOfReallyVeryLongStringNames[439]; // no compile
I do understand that strings are immutable in C#. I also understand that you cannot get the address of a managed object.
I'd like to do this:
a = "Donkey Kong"; // Now ArrayOfReallyVeryLongStringNames[439] = "Donkey Kong";
I have read the Stack Overflow question Make a reference to another string in C#
which has an excellent answer, but to a slightly different question. I do NOT want to pass this parameter to a function by reference. I know how to use the "ref" keyword for passing a parameter by reference.
If the answer is "You cannot do this in C#", is there a convenient workaround?
EDIT:
Some of the answers indicate the question was unclear. Lets ask it in a different way. Say I needed to manipulate all items in the original long-named array that have prime indices. I'd like to add aliases to Array...[2], Array...[3], Array...[5], etc to a list. Then, modify the items in the list using a "for" loop (perhaps by passing the list just created to a function).
In C# the "using" keyword creates an alias to a class or namespace. It seems from the answers, that it is not possible to create an alias to a variable, however.
You could create a wrapper that keeps a reference to the underlying array AND the index of the string:
public sealed class ArrayStringReference
{
private readonly string[] _array;
private readonly int _index;
public ArrayStringReference(string[] array, int index)
{
_array = array;
_index = index;
}
public string Value
{
get
{
return _array[_index];
}
set
{
_array[_index] = value;
}
}
public override string ToString()
{
return Value;
}
}
Then this will work:
string[] ArrayOfReallyVeryLongStringNames = new string[500];
ArrayOfReallyVeryLongStringNames[439] = "Hello world!";
var strRef = new ArrayStringReference(ArrayOfReallyVeryLongStringNames, 439);
Console.WriteLine(ArrayOfReallyVeryLongStringNames[439]); // Outputs "Hello world!"
strRef.Value = "Donkey Kong";
Console.WriteLine(ArrayOfReallyVeryLongStringNames[439]); // Outputs "Donkey Kong"
You could make this more convenient to use by providing an implicit string operator so you don't have to use .Value to access the underlying string:
// Add this to class ArrayStringReference implementation
public static implicit operator string(ArrayStringReference strRef)
{
return strRef.Value;
}
Then instead of having to access the underlying string like this:
strRef.Value = "Donkey Kong";
...
string someString = strRef.Value;
You can do this:
strRef.Value = "Donkey Kong";
...
string someString = strRef; // Don't need .Value
This is just syntactic sugar, but it might make it easier to start using an ArrayStringReference in existing code. (Note that you will still need to use .Value to set the underlying string.)
The closest you can get is this:
unsafe
{
string* a = &ArrayOfReallyVeryLongStringNames[439]; // no compile
}
Which gives an exception:
Cannot take the address of, get the size of, or declare a pointer to a managed type ('string')
So no, not possible...
Also read this MSDN article which explains what types can be used (blittable types).
When I do something like this in C#:
string a = "String 1";
string b = a;
a = "String 2";
Console.WriteLine(a); // String 2
Console.WriteLine(b); // String 1
The thing is, both "String 1" and "String 2" literals are created at the start of the program, and strings are always pointers: at first a references "String 1" literal and afterwards it references "String 2". If you want them to always reference the same thing, in C# you just use the same variable.
The string objects themselves are immutable in C#:
Because a string "modification" is actually a new string creation, you must use caution when you create references to strings. If you create a reference to a string, and then "modify" the original string, the reference will continue to point to the original object instead of the new object that was created when the string was modified.
When the string mutability is needed, for example, to concatenate a lot of strings faster, other classes are used, like StringBuilder.
To sum it up, what you're trying to do is impossible.
In C#, a String is an Object. Therefore String a = "Donkey Kong" says that a now have a reference to this string that is being allocated over the memory. Then all you need to do is:
ArrayOfReallyVeryLongStringNames[439] = a;
And that will copy the refrence (which you should be thinking of in C#!!!) to the location in the string.
BUT!! When you do a="new string";, a will get a new reference. See the example I made:
http://prntscr.com/3kw18v
You can only do this with unsafe mode.
You could create a wrapper
public class StringWrapper
{
public string Value {get;set;}
}
StringWrapper[] arrayOfWrappers = new StringWrapper[500];
arrayOfWrappers[439] = new StringWrapper { Value = "Hello World" };
StringWrapper a = arrayOfWrappers[439];
a.Value = "New Value";
What you are trying to do is universally discouraged, and actively prevented, in C#, where the logic should be independent of the memory model, however, refer to related SO question C# memory address and variable for some info.
EDIT 1
A more canonical approach to your actual problem in C# would be:
// using System.Linq;
string[] raw = new string[] { "alpha", "beta", "gamma", "delta" };
List<int> evenIndices = Enumerable.Range(0, raw.Length)
.Where(x => x % 2 == 0)
.ToList();
foreach (int x in evenIndices)
raw[x] = raw[x] + " (even)";
foreach (string x in raw)
Console.WriteLine(x);
/*
OUTPUT:
alpha (even)
beta
gamma (even)
delta
*/
If you really want to modify the original memory structure itself, then perhaps C++ is a more appropriate language choice for the solution.
EDIT 2
Looking around on SO, you may want to look at this answer Hidden Features of C#? to an unrelated question.
[TestMethod]
public void TestMethod1()
{
string[] arrayOfString = new string[500];
arrayOfString[499] = "Four Ninty Nine";
Console.WriteLine("Before Modification : {0} " , arrayOfString[499]);
string a = arrayOfString[499];
ModifyString(out arrayOfString[499]);
Console.WriteLine("after a : {0}", a);
Console.WriteLine("after arrayOfString [499]: {0}", arrayOfString[499]);
}
private void ModifyString(out string arrayItem)
{
arrayItem = "Five Hundred less one";
}
Of course you can, hehe:
var a = __makeref(array[666]);
__refvalue(a, string) = "hello";
But you would have to have a very good reason to do it this way.
I am in need of some help here about doing a dynamic instantiation in C#. What I want to accomplish is to be able to use a string variable that is used as the name in the instantiation. I think you can use reflection or something, but I am lost on this one. Here is my test code snippet and hopefully someone has an answer.
Averages is tied to a class that handles everything. So lets say I wanted to make test the variable and everything that is tied to the string of test could be passed as the instantiation. How could I create an object that can handle the variable test coming in, compile and be used in runtime? I know this may sound out of the ordinary, but instead of me using many IF's with multiple declarations of doubles. I could use a dynamic instantiation. Anyone that can help out I would be most appreciative.
Averages test = new Averages();
double[] testresult;
testresult = test.sma();
womp,,,I want to dynamically declare arrays of doubles. I already know how to declare a static array. What I am trying to accomplish is eliminating declaring 30 arrays that bascially do the same thing over and over again with a different naming.
So instead of doing this:
if (UITAName == "SMA")
{
Averages sma = new Averages();
double[] smaresult;
smaresult = sma.sma(UITAName, YVal, UITPeriod, UITShift);
chart1.Series[UITA].Points.DataBindXY(test2, test1);
}
if (UITAName == "TMA")
{
Averages tma = new Averages();
double[] tmaresult;
tmaresult = tma.tma(UITAName, YVal, UITPeriod);
chart1.Series[UITA].Points.DataBindXY(XVal, tmaresult);
}
else
if (UITAName == "EMA")
{
Averages ema = new Averages();
double[] emaresult;
emaresult = ema.ema(UITAName, YVal, UITPeriod);
chart1.Series[UITA].Points.DataBindXY(XVal, emaresult);
}
I want to do this only once for everything instead of doing IF statements. The problem is that you cannot compile with a declaration of a string. There has to be a way I just do not know how.
Averages UITAName = new Averages();
double[] UITANameresult;
UITANameresult = UITAName.UITAName(UITAName, YVal, UITPeriod);
chart1.Series[UITA].Points.DataBindXY(XVal, UITANameresult);
You can instantiate a class dynamically using Reflection, with Activator.CreateInstance.
Activator.CreateInstance("MyAssembly", "MyType");
However I'm not entirely clear on what you're trying to do. If you already have a class called Averages, what do you need dynamically instantiated? And I'm a bit worried by what you mean that it's "tied to a class that handles everything"...
Sounds like you might need to check out Func<> ??? Just my initial assessment without seeing a little more code to give me a clearer context.
To clarify, if you are wanting to pass the values as an argument, like you would on your command line, then you would need to instance the assembly. Otherwise, with Func<T, TResult> you can pass parameters dynamically to a method and get the return value.
Okay...if I get what you are saying...you want something that would resemble:
class Average
{
public double[] sma()
{
// do something
return dArray;
}
public double[] ema()
{
// do something
return dArray;
}
}
that is...the function 'name' would be the value of the string returned from a database query of some sort?
...and if that is the case then I don't know why you wouldn't just do a dictionary like:
Dictionary<string, double[]> testResults = new Dictionary<string, double[]>();
void GetDoubles(string name, params double[] args)
{
testResult[s] = GetAverages(args);
}
I think this could help you.
If i understand you correctly, you have method initinialization values in db as SMA,EMA,etc and you need to invoke the method at runtime,
string invokeMethod = GetValueFromDB() //ur logic to get the SMA or EMA or TMA from db
Type urType=typeof("yourclassname");
object unKnownObj = Activator.CreateInstance(urType);
//Fill your paramters to ur method(SMA,EMA) here
//ie, sma.sma(UITAName, YVal, UITPeriod, UITShift);
object[] paramValue = new object[4];
paramValue[0] = UITAName;
paramValue[1] = YVal;
paramValue[2] = UITPeriod;
paramValue[3] = UITShift;
object result=null;
try
{
result = urType.InvokeMember(invokeMethod, System.Reflection.BindingFlags.InvokeMethod, null, unKnownObj, paramValue);
}
catch (Exception ex)
{
//Ex handler
}
So this way you can avoid the multiple if loops and will invoke the method directly by the given name..
I think reflection might not be the best solution for your situation. Maybe decomposing your code a little bit might help, something along the following lines...
public interface ICalculation
{
double [] Calculate(double y, double period, double shift);
double XVal {get;}
}
public class SMA : ICalculation
{
public override double[] Calculate( double y, double period, double shift )
{
// do calculation, setting xval along the way
}
// more code
}
public class EMA : ICalculation
{
public override double[] Calculate( double y, double period, double shift )
{
// do calculation, setting xval along the way
}
// more code
}
public class Averages
{
public void HandleCalculation( ICalculation calc, double y, double p, double s )
{
double[] result = calc.Calculate( y, p, s );
chart.Series[UITA].Points.DataBindXY( calc.XVal, result );
}
}