Why is "someString += AnotherString = someString;" valid in C# - c#

I was writing some code today and was mid line when I alt-tabbed away to a screen on my other monitor to check something. When I looked back, ReSharper had colored the 3rd line below grey with the note "Value assigned is not used in any execution path".
var ltlName = (Literal) e.Item.FindControl("ltlName");
string name = item.FirstName;
name +=
ltlName.Text = name;
I was confused; surely this code can't compile. But it does, and it runs too. The line "name +=" has no effect (that I could tell) on the string. What's going on here?
(Visual Studio 2008, .NET 3.5)

Notice that newlines are not special in C#. Because of the following line, the complete statement to the compiler is
name += ltlName.Text = name;
which is a valid statement (it assigns name to ltlName.Text, then append it to name.)

It's doing this:
name += ltlName.Text = name;
or to make it slightly clearer:
name += (ltlName.Text = name);
The result of the property setter is the value which was set, so it works a bit like this:
string tmp = name;
ltlName.Text = tmp;
name += tmp;
It's simpler to observe this when you've got different variables involved though, and just simple assignment as the final step rather than a compound assignment. Here's a complete example:
using System;
class Test
{
public string Text { get; set; }
static void Main()
{
Test t = new Test();
string x = t.Text = "Hello";
Console.WriteLine(x); // Prints Hello
}
}
The simple assignment rules (section 7.17.1) are used to determine the result of the expression:
The result of a simple assignment
expression is the value assigned to
the left operand. The result has the
same type as the left operand and is
always classified as a value.
So the type of ltlName.Text = name is the same type as ltlName.Text, and the value is the one that's been assigned. The fact that it's a property rather than a field or local variable doesn't change this.

In C#, newlines don't terminate statements - only semicolons do. So the following line of code is executing:
name += ltlName.Text = name;

Because whitespace is irrelevant in C#, line 3, 4 and 5 form one statement:
name += ltlName.Text = name;

As expected, the result is name concatenated to itself. So you get "namename".
obj.Text is just a property, so the line ends up converting to
//name += obj.Text = name;
obj.setText(name);
name += obj.Text;
Full source below
public class Program
{
public static void Main(string[] args)
{
MyClass obj = new MyClass();
string name = "name";
name += obj.Text = name;
Console.Write(name); //prints namename
}
}

It is affecting the string, but not until after the string is used to affect the literal on the display. As KennyTM pointed out, both lines form a single statement. Unlike VB, the carriage return doesn't end a statement in C#. The semicolon does. So what's happening here is the string is being set to the literal, and the result of that operation ("true" perhaps? or just the string itself? I don't remember) is being appended to the string.

Related

How to evaluate single string in IF c#

is it possible to evaluate a single string in c#. The string itself will only be determined during run-time and therefore cannot be set before hand. please see example:
var a = "a == b";
if(a){
//do something
}
EDITED:
This is a actual example of what i would like computed:
var evaluationToBeDone = "MUST_CE_I = \"MUST_CE_I\"";
if(evaluationToBeDone){
// i will do something if the above is true
}
I see what you're trying to do, but the approach doesn't make sense. When you make a variable into an object, the program only reads it as letters, not any logic inside of the object. Try doing this:
var a = "MUST_CE_I"
var b = "\"MUST_CE_I\""
if (a == b)
{
do stuff
}
I assume you want your second string to have the " " quotes, so this should give you what you need. Even though the if statement will always return false since the two variables are not equal.

Read only assignment String c#

I'm trying to assign "tela[counter] = letra.ToString();", but it shows up the following error message "Property or indexer 'string.this[int] cannot be assigned to -- it is read only".
I saw some topics saying that you have to define {get;set;} to the atribute, but I've done this, and it didn't work.
[OBS] I tried to create get and set methods but the problem persisted
public String tela { get; set; }
private void btnSendWord_Click(object sender, EventArgs e)
{
char letra = Convert.ToChar(txtGetWord.Text);
MessageBox.Show(comboPalavra[0]);
Boolean codigoVerificador;
codigoVerificador = verificador.VerificaLetra(comboPalavra[0],letra);
if (codigoVerificador == true)
{
foreach(char c in comboPalavra[0].ToCharArray())
{
counter++;
if(c == letra)
{
tela[counter] = letra.ToString();
}
}
}
else MessageBox.Show("Nao contem");
}
Strings are immutable, meaning that you can't change a variable's value without creating a new string.
You are trying to change a single character in a string here, which is not allowed:
tela[counter] = letra.ToString();
A solution to this is to use StringBuilder. You can think of it as a mutable version of string.
You can declare a StringBuilder outside the loop:
var telaBuilder = new StringBuilder(tela);
In the loop, change the erroneous line to:
telaBuilder[counter] = letra;
And after the loop, assign telaBuilder to tela:
tela = telaBuilder.ToString();
Don't forget using System.Text!
This is the signature of the indexer for a string:
public char this[int index] { get; }
See that it returns a char and only has a get, that means it is readonly and you cannot assign something to it. This is why you are getting the error.
If you want to replace a specific letter in a string at a specific position, you can do it like this:
var name = "ferry Seinfeld";
char[] nameArray = name.ToArray();
nameArray[0] = 'J';
name = new string(nameArray);
Please look into Replace method of String and also look into StringBuilder class to see if those will suit your needs.

The name does not exist in the current context - grrr

In the following code, no matter what I try, the name strSide "does not exist in the current context", when I place a break point as shown. I want strSide to contain the last character in rawId and then to strip that character so that the value of rawId will convert to an integer. I don't get a compiler error, but do get a runtime error.
When the value of rawId is 8429R, the stripping works, but I cannot get the R assigned to strSide.
foreach (string fieldName in Request.QueryString)
{
rawId = fieldName;
String strSide = Convert.ToString(rawId[rawId.Length - 1]); <-- name does not exist
if (!IsNumeric(rawId)) <--break point set here.
{
rawId = StripRightChar(rawId);
}
Qty = Request.QueryString[fieldName];
int productId = 0;
if (fieldName == "txtReference")
{
strComments = Request.QueryString[fieldName];
}
Might the variable have been "optimized away"? It is not used anywhere after its creation. See this for details: How to prevent C# compiler/CLR from optimizing away unused variables in DEBUG builds?.
Do you need the value stored in strSide?
If not you could try this alternative solution
Update, since you need the value, try this:
var s = "8429L";
var numbers = s.Substring(0, s.IndexOfAny("RLB".ToCharArray()));
var letter = s.Substring(numbers.Length);

Do synonyms exist?

Is there a way to have a variable set to an object and have another variable which is always equals to the former one?
var x = new object();
var y = [synonym of x];
x = null; // then y = null as well
I don't think this exists.
So I've often used arrays to hold "references".
var x = new object[] { new object() };
var y = x;
x[0] = null; // then y[0] = null as well
But it feels kinda lame.
If you really really need to this you can do something like below but I think it is still lame (:
class RefHolder<T>
{
public RefHolder(T value)
{
Value = value;
}
public T Value { get; set; }
}
Usage
var o1 = new RefHolder<object>(new object());
var o2 = o1;
o2.Value = null; // now o1.Value is null too
You can do it but the price you have to pay is to use undocumented keywords/features. They're there from long time ago and probably they won't change or disappear but...
It'll make your code more complicated to read (it may be useful if supported by the language itself) but it's bidirectional and you can move around your original object, changes will always be reflected to your "reference" too. It differs from Mehmet Ataş answer because you can pass the original object to another function and changes will propagate to your synonym too. They have limitations (they can't be used for class fields) but they works for parameters and local variables.
What you need is a TypedReference, it holds a reference to another variable then if you assign a new value to it you'll change the original variable. This in theory could open the door to synonyms if someday they'll think it's a good feature to include.
Let's see an example:
var text = "initial value";
var synonym = __makeref(text);
Now synonym is a reference to text (please note it's a reference to text and not to the value it holds). To get original value from a TypedReference you use __refvalue like this:
Console.WriteLine(__refvalue(synonym, string));
They have the same value:
Debug.Assert(__refvalue(synonym, string) == text);
Now let's change text to a new value:
text = "second value";
Debug.Assert(__refvalue(synonym, string) == text);
And even opposite is true:
__refvalue(synonym, string) = "third value"; // <---
Debug.Assert(__refvalue(synonym, string) == text);
Finally let's modify the original variable within another function (unaware of the reference it'll see a normal variable):
void ChangeIt(ref string value) { value = "another value"; }
ChangeIt(ref text);
Debug.Assert(__refvalue(synonym, string) == text);
All of this works will value types as well. Note that this creates a synonym for a variable, not an alias (you can imagine them as a safe pointer - to pointer in case of reference type). Let's try this:
void foo1()
{
string text = "ABC";
foo2(text);
// text holds the original value "ABC"
// not the value modified in foo2
}
void foo2(string value)
{
value = "123";
var synonym = __makeref(value);
__refvalue(value, string) = "456";
// both value and synonym holds "456";
}
Well, you are basicly describing a C++ reference (or a C pointer).
This can be done in C#, too, but you REALLY do not want to do this unless you absolutely need to.
unsafe static void Main(string[] args)
{
int a = 5;
int *b = &a;
*b = 0;
Console.WriteLine(a);
}
This will output 0 to the console.
You can read more about unsafe code in Unsafe Code and Pointers article on MSDN.
It depends. .NET contains both Reference and Value types. Value types are all the basic types, int, bool etc.. plus string. Reference types are everything else, including anything you create for yourself.
So, for example, value types...
int a = 3;
int b = a;
b = 5;
// a is still 3
While with references
class Mine {
public int A { get; set; }
}
Mine A = new Mine() { A = 3; }
Mine B = A;
B.A = 5;
// A.A is now 5.
you can asign like
var parentObject={};
parentobject['child1']="test1";
parentobject['child2']="test2";
parentobject['child3']="test3";
after
console.log(parentObject);
you get following output
object{child1="test1",child2="test2",child2="test2"}

send a String array as parameter to a function

I have a function in a class called Function, like below:
public int SearchedRecords(String [] recs)
{
int counter = 0;
String pat = "-----";
String[] records = recs;
foreach (String line in records)
{
if (line.Contains(pat) == true)
{
counter++;
}
}
return counter;
}
And I am calling this method from my main class this way:
String [] file = File.ReadAllLines("C:/Users.../results.txt");
int counter = Function.SearchedRecords( []file);
But I get an error saying:
;expected
What is wrong?
Another question: The function above is counting from a file all the lines with the pattern ----- in them (even if with more dashes, or if the line has some chars before or after the dashes). Am I right?
It's something like the patterns in Java so maybe there is an other way.
Can you enlighten me?
Remove the [] from your parameter.
e.g.
int counter = Function.SearchedRecords(file);
And yes, your assumption about the behavior of the Contains method is correct - you'll match any line containing five consecutive dashes, regardless of what characters are before or after them.
If you want to parse for exactly five dashes, with nothing before or after them I suggest looking into the RegEx class (regular expressions).
Change
int counter = Function.SearchedRecords( []file);
to
int counter = Function.SearchedRecords(file);
and yes, this will work, for that string.
However Contains is case sensitive, if you were matching on a name, or another string with alphabetic characters, the case would have to be identical to match e.g. line.Contains("Binary Worrier") will not match a string "Hello binary worrier".
Also, reading the entire file into memory is fine if you know that the file will always be small, this method gets less efficient the larger the file.
Better to always use something like System.IO.StreamReader or System.IO.File.ReadLines (available in .Net 4 and later), these allow you to consume the file one line at a time. e.g.
using (var reader = new System.IO.StreamReader("MyFile.txt"))
{
while(!reader.EndOfStream)
{
string line = reader.ReadLine();
if (line.Contains(pattern))
counter++;
}
}
Change it to
int counter = Function.SearchedRecords(file);
Remove '[]' from a method call. Yes, your function seems to count what you want.
First of all you need to create an instance of function class and then run the function. Hope following code helps
Function fb = new Function();
int counter = fb.SearchedRecords(file);
Right now, you are using SearchRecords as an static function of a static class which doesn't require instantiation.
You can do this in a shorter way using LINQ:
int counter = file.Count(line => line.Contains("-----"));

Categories

Resources