This question already has answers here:
Cannot assign null to an implicitly-typed variable
(4 answers)
Closed 3 years ago.
I have an else block containing two for loops.
With the second for loop I am trying to create a set of objectYouCreate instances from a clean slate, as in if a set of instances was previously made, it was already successfully destroyed via the first for loop. So each time this code runs (in the Update method), it is creating an entirely new set of instances after wiping the previous set.
This is the (could be flawed) logic I came up with to do that, but I'm getting this error:
Error: "Cannot assign <null> to implicitly typed variable"
Can I receive help with how to best restructure this code logically and without errors. Thank you.
else{
var objectYouCreate = null; //gives the error
for (int i = 0; i < mesh.vertexCount; i++)
{
Destroy(objectYouCreate);
}
for (int i = 0; i < mesh.vertexCount; i++)
{
Vector3 position = mesh.vertices[i];
objectYouCreate = Instantiate(CubePrefab, position, transform.rotation);
}
}
__
edit:
By introducing usage of tags to my code... I was able to change the code so that the only var declaration happens inside a single for loop and is not null.
I'm also trying to utilize the tags for the Destroy portion, so that it does not just focus the same object but instead focuses all objects with the given tag upon instantiate. But this new code crashes Unity! If anyone has suggestions for optimization or a different method please let me know.
else
{
while (GameObject.FindWithTag("CubePFInst") != null) Destroy(GameObject.FindWithTag("CubePFInst"));
for (int i = 0; i < mesh.vertexCount; i++)
{
Vector3 position = mesh.vertices[i];
var cubeClone = Instantiate(CubePrefab, position, transform.rotation);
cubeClone.tag = "CubePFInst";
}
}
var was introduced for compile-time type-binding for anonymous types yet we can use var for primitive and custom types that are already known at design time. At runtime there's nothing like var, it is replaced by an actual type that is either a reference type or value type.
References:
var (C# Reference)
https://www.itorian.com/2015/04/initialize-var-with-null-or-empty-in-c.html
Related
This question already has answers here:
Closures in C# - initating a thread in a function call with a value type
(3 answers)
Closed 3 years ago.
I have a problem with my multi threading app.
I have an array with 4 Threads in it.
Here is how I initialize them:
for (int i = 0; i < threads.Length; i++)
{
threads[i] = new Thread(delegate () { ThreadMethod(i); });
}
But after my first test(s) I showed that all four threads run with 3 as passed value.
I chagend it to
for (int i = 0; i < threads.Length; i++)
{
int id = i;
threads[i] = new Thread(delegate () { ThreadMethod(id); });
}
and it worked but for me it looks like there must be a better way to pass my i to my thread.
Am I right with my guess and if I am, how should I pass i?
Thank you!
The closure uses local variables -- in a for loop the variables declared for the loop are not local they have to be inside the block ({}) for that. That is why the 2nd example works.
The delegate keyword is what creates the closure and it looks for local variables to include in the closure. When it finds id it includes it. When it doesn't it references the global (outside the closure) value of i and at the time of running i has a value of 3.
This question already has answers here:
Will using 'var' affect performance?
(12 answers)
Closed 3 years ago.
I have noted in c# that using var improves your performance, especially when declaring variables of a specific class. I have done multiple bench marks and have got the same result every time. I have also read similar questions on this site and others. but no one has actually commented on this.
Can anyone please confirm or refute this.
I have a
class for image data, clsImageData
and collection clsImageDataCollection.
a function in collection class is SetCaseLowerCase().
Code is
private void SetCaseLowerCase()
{
foreach (var item in this)
{
item.DestinationImageName = item.DestinationImageName.ToLower();
}
}
Now if I use clsImageData instead of var, it performs slower, I have checked it with 100000 iterations. but results is always the same. also with other examples too.
Thanks
Edited
I have tested this simple code and got 7/10 times better performance using var. Please tell me what am I doing wrong, I am using VS 2017, debug mode for any CPU, my processor is quad core. Thanks
sw.Start();
for (int i = 0; i < 10000000; i++)
{
var xyz = "test";
}
StopClock(sw, "Example var - ");
sw.Start();
for(int i = 0; i<10000000; i++)
{
string xyx2 = "test";
}
StopClock(sw, "Example type - ");
var is compiled in a way, that makes the use of it equals to just declaring the variable/ type (except in cases it cant be done somehow else but using var ex: anonymous types). that means there are no performance changes at all. read more about var at https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/var
here is a demonstration, type the following code:
var list = new List<int>();
note that when you hover above list your IDE says:
(local variable) List<int> list
the reason for that is that var is converted to the declared type, meaning that var is actually cosmetic and its use can not impact any performance.
This question already has answers here:
Captured variable in a loop in C#
(10 answers)
Closed last month.
I have this code and do not understand why the out put is 22! I am afraid it should be 01!
can anyone explain what happens? if the list store a method with a parameter, so the parameters should be 0 and 1 respectively!
List<Action> list = new List<Action>();
for (int i = 0; i < 2; i++)
{
list.Add(() => Console.Write(i));
}
foreach (var it in list)
{
it();
}
It is Closure (1, 2).
In your case Console.Write(i) will use value of i in the moment of action call. You firstly increment i in for loop then in second loop you call every action in the list. In the moment of call of every action i has value 2 - so, you get 22 as output.
To get expected result you should create local copy of i and use it:
for (int i = 0; i < 2; i++)
{
var temp = i;
list.Add(() => Console.Write(temp));
}
Addition to Roma Doskoch's anwser, another approach is to avoid for.
var list = Enumerable
.Range(0, 2)
.Select<int, Action>(i => () => Console.Write(i));
Closures capture variables, not values.
In your code, the closure captures the variable i, not whatever value happens to be stored in i on each iteration. When you invoke the action, the variable i has a value of 2 (because the loop has finished) and therefore 2 will be printed out twice.
In order to avoid this, as other answers already point out, you need to create a new variable every time around as a workaround to not being able to capture values; if you declare a new variable on every iteration then the result of capturing the variable is equivalent to capturing the value because you won't be changing it on the next iteration.
This question already has answers here:
Variable scope confusion in C#
(4 answers)
Closed 9 years ago.
Is there any practical difference (speed, memory) between these two ways of declaring (introducing) variables? Which one is the better way?
Example 1:
for (int i = 0; i < myObjects.Length; i++)
{
MyObject m = myObjects[i];
}
Example 2:
MyObject m = null;
for (int i = 0; i < myObjects.Length; i++)
{
m = myObjects[i];
}
Thanks.
Example 1 makes it so that m is only "alive", in memory, within the scope of the for loop.
Example 2 makes it so that m stays occupying memory after the for loop finishes executing.
I would go with example 1, this is why:
Declaring variables inside or outside of a loop (I won't really tell you, in detail, to force you to read the link.)
Performance-wise both are compiled to the same IL, so there's no difference.
The first one is better because you are meaning to have a new object in each iteration. Also there is no need to have an object if the loop condition fails
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Child Scope & CS0136
C# Variable Scoping
Though I have been using C# for quite some time, I have just stumbled upon this error.
If I have the following:
if(true)
{
int x = 0;
}
int x = 0;
I get an error that says: A local variable named 'x' cannot be declared in this scope because it would give a different meaning to 'x', which is already used in a child scope to denote something else.
And if I do this:
if(true)
{
int x = 0;
}
x = 0;
I get an error that says: The name 'x' does not exist in the current context.
I can understand having one or the other, but why do both of these errors exist? Is there a way around the first option? I find it very annoying.
Thanks.
Both of these errors exist to stop you from making mistakes or causing your colleagues to want to kill you.
The first fails because it's confusing to have two identically named local variables both in scope at a time.
The second fails because the variable's scope is the if statement, and you're trying to access it outside that scope.
If you want a single variable which you can use both inside and outside the block, you just need to declare it before the block:
int x;
if (true)
{
x = 0;
}
x = 0;
If you actually want two separate variables to be in scope at the same time (within the block), then give them different names - thereby avoiding later confusion.
EDIT: You can declare multiple local variables with the same name in a single method, but they have to have separate scopes. For example:
public void Foo(IEnumerable<string> values)
{
double sum = 0;
foreach (string x in values)
{
int z = x.Length;
sum += z;
}
foreach (string x in values)
{
double z = double.Parse(x);
sum += z;
}
}
Personally I don't tend to use this ability very often - at least not with different types - when the variables have meaningful names and methods are short. But it's absolutely legitimate, and can certainly be useful sometimes.
In the first case, the problem is that your int x outside the { } block has a global scope that encloses the context inside { }; therefore you are re-declaring a variable with the same name.
In the second case; x does not exist as it is only defined inside { }