In my last c# interview, I was asked to prove immutability of C# string,I know what is meant by immutability of c# string,But is it possible to prove immutability of c# string through code ? can i have a sample code snippet please.
Thanks in advance
I can prove that a string is not immutable. All I need to do is to show some code which mutates a string, like so:
using System;
using System.Runtime.InteropServices;
namespace Demo
{
class Program
{
static void Main(string[] args)
{
const string test = "ABCDEF"; // Strings are immutable, right?
char[] chars = new StringToChar {str = test}.chr;
chars[0] = 'X';
// On an x32 release or debug build or on an x64 debug build,
// the following prints "XBCDEF".
// On an x64 release build, it prints "ABXDEF".
// In both cases, we have changed the contents of 'test' without using
// any 'unsafe' code...
Console.WriteLine(test);
// The following line is even more disturbing, since the constant
// string "ABCDEF" has been mutated too (because the interned 'constant' string was mutated).
Console.WriteLine("ABCDEF");
}
}
[StructLayout(LayoutKind.Explicit)]
public struct StringToChar
{
[FieldOffset(0)] public string str;
[FieldOffset(0)] public char[] chr;
}
}
Now whether this should be considered a bug in C# is a different matter. :)
(The answer is probably that FieldOffset should be considered to be unsafe - the code above is purportedly safe and therefore the string should not be mutatable.)
Also, I think you could legitimately argue that string is immutable in spirit, even if there are silly edge cases which violate its immutability in supposedly safe code.
Yes, It is possible to prove immutability of c# string using ObjectIDGenerator Class.
Following answer is taken from dotmob article on String Vs Stringbuilder in C#
Actually ObjectIDGenerator will return an unique integer value for instances that we created in our programs.With the help of this class we can check whether new instance is created or not for various operations on string and stringbuilder .Consider following program
using System;
using System.Text;
using System.Runtime.Serialization;
class Program
{
static void Main(string[] args)
{
ObjectIDGenerator idGenerator = new ObjectIDGenerator();
bool blStatus = new bool();
//just ignore this blStatus Now.
String str = "My first string was ";
Console.WriteLine("str = {0}", str);
Console.WriteLine("Instance Id : {0}", idGenerator.GetId(str, out blStatus));
//here blStatus get True for new instace otherwise it will be false
Console.WriteLine("this instance is new : {0}\n", blStatus);
str += "Hello World";
Console.WriteLine("str = {0}", str);
Console.WriteLine("Instance Id : {0}", idGenerator.GetId(str, out blStatus));
Console.WriteLine("this instance is new : {0}\n", blStatus);
//Now str="My first string was Hello World"
StringBuilder sbr = new StringBuilder("My Favourate Programming Font is ");
Console.WriteLine("sbr = {0}", sbr);
Console.WriteLine("Instance Id : {0}", idGenerator.GetId(sbr, out blStatus));
Console.WriteLine("this instance is new : {0}\n", blStatus);
sbr.Append("Inconsolata");
Console.WriteLine("sbr = {0}", sbr);
Console.WriteLine("Instance Id : {0}", idGenerator.GetId(sbr, out blStatus));
Console.WriteLine("this instance is new : {0}\n", blStatus);
//Now sbr="My Favourate Programming Font is Inconsolata"
Console.ReadKey();
}
}
Output Will look like this
Instance id for string get changed from 1 to 2 when str concatenated with “Hello World”.while instance id of sbr remains same as 3 after append operation also. This tells all about mutability and immutability. blStatus variable indicate whether the instance is new or not.
You can find complete article on the topic from : http://dotnetmob.com/csharp-article/difference-string-stringbuilder-c/
Related
Hello guys, I don't need the answer but I would look to know and find out what I'm doing wrong. As a beginner I got a very "easy" assignment in my studies. I need to create a string and inside this string I need to replace some words by other words without using the for loop as so: ( also I want to print it but I got no clue where to put Console.WriteLine and google searching for 1 hour didn't work or asking a colleage.
/* Excersice: use with stringbuilder
* cat becomes littlecat
* dog becomes littledog
* mouse becomes littlemouse
* words the must be replace by a
* do not use a loop*/
using System;
using System.Collections.Generic;
using System.Text;
namespace Opgavens_leerpad_3_oefening
{
class Program
{
static string Main(string[] args)
{
StringBuilder sb = new StringBuilder();
string dogCat = new string("Can the cat find the mouse without waking the dog.");
static string replacethisstring(string dogCat);
{
hondKat = dogCat.Replace("cat", "littlecat");
hondKat = dogCat.Replace("dog", "littldog");
hondKat = dogCat.Replace("mouse", "littlemouse");
hondKat = dogCat.Replace("the", "a");
return dogCat;
}
}
}
}
Error CS5001: Program does not contain a static "Main" method suitable for an entry point ( I don't get this doesn't almost any program starts with this static Main args? )
Error CS8112: replacethisstring(string)' is a local function and must therefore always have a body. ( I just gave it a body right? I opened the { and close it } and put a replace with return. )
The method declaration ends with ; that’s the reason for CS8112
The Main method has to return void (or ‘int’ )you’ve modified it to string, that’s the reason for CS5001
If you want the program to print the output on the console use:
using System;
....
Console.WriteLine(output)
Your main should have a void as return type. string is not allowed but int is an option (see reference)
You cannot have ; at the end of a function declaration that has a body to it.
You have to declare a variable before you can use it ... string hondKat;
See the use of StringBuilder in the below code instead of string.
namespace Opgavens_leerpad_3_oefening
{
class Program
{
public static void Main(string[] args)
{
StringBuilder sb = new StringBuilder();
sb.Append("Can the cat find the mouse without waking the dog.");
sb = replacethisstring(sb);
Console.WriteLine(sb.ToString());
Console.ReadLine(); // To Stop the Console from closing.
static StringBuilder replacethisstring(StringBuilder dogCat)
{
dogCat = dogCat.Replace("cat", "littlecat");
dogCat = dogCat.Replace("dog", "littldog");
dogCat = dogCat.Replace("mouse", "littlemouse");
dogCat = dogCat.Replace("the", "a");
return dogCat;
}
}
}
}
You can place the function within the Main or outside. Normally you would find functions outside of the Main class.
public static void Main(string[] args)
{
...
}
public static string replacethisstring(string dogCat)
{
...
}
Having several issues like typos, syntax error etc.
Additionally, the excercise having a condition that needs to use with stringbuilder.
So, try this.
static void Main(string[] args)
{
StringBuilder sb = new StringBuilder("Can the cat find the mouse without waking the dog?");
sb = replacethisstring(sb);
Console.WriteLine(sb.ToString());
Console.ReadLine();
}
static StringBuilder replacethisstring(StringBuilder dogCat)
{
StringBuilder hondKat = dogCat.Replace("cat", "littlecat");
hondKat = dogCat.Replace("the", "a");
hondKat = dogCat.Replace("dog", "littledog");
hondKat = dogCat.Replace("mouse", "littlemouse");
return hondKat;
}
Im trying to get the class variable name
static void Main()
{
TaskAction m_first = new TaskAction();
m_first.Increment();
m_first.Increment();
TaskAction m_Second = new TaskAction();
m_Second.Increment();
}
public class TaskAction
{
private int m_Current;
public TaskAction()
{
m_Current = 0;
}
public void Increment()
{
m_Current++;
write(" TaskAction " + vairableName + " " + m_Current);
}
}
i want to it to write out:
TaskAction m_first 1
TaskAction m_first 2
TaskAction m_second 1
Retrieving metadata about your program like that is both complex and unnecessary, just add the name by passing it to the constructor.
static void Main()
{
TaskAction m_first = new TaskAction("m_first");
m_first.Increment();
m_first.Increment();
TaskAction m_Second = new TaskAction("m_Second");
m_Second.Increment();
}
public class TaskAction
{
private int m_Current;
private string m_taskName;
public TaskAction(string taskName)
{
m_taskName = taskName;
m_Current = 0;
}
public void Increment()
{
m_Current++;
write(" TaskAction " + m_taskName + " " + m_Current);
}
}
Short Answer: You can't.
Long Answer:
Technically, it's possible to determine a variable name by inspecting the IL (the intermidate language created by the C# compiler), but this operation is hard and error-prone. Also, you ignore some important questions:
First of all, as already asked here: Why? how such thing will enhance your program?
Each instance of the class can have multiple variables pointing to it (see my answer about types in .NET here). Which of them you want to get? For example, consider the following program:
var v1 = new TaskAction();
var c2 = new TaskAction();
c1.Increment(); // 1 c1
c2 = c1;
c2.Increment(); // 2 c1? 2 c2? 2 c1 c2?
By doing so, you break the encapsulation in a difficult way - any reflection breaks the encapsulation, and really don't use it unless you really need it - but so much? Reflection breaks the hidden information about the private interface, you question breaks the internal interface!
Since you didn't give enough information, I can't know why you tought you need that. But here is some solutions:
If you want, for example, logging with categories - simply pass the category to the constructor, as sugegsted above.
If you want to know which type the variable is - using its name is very very very bad approach, even though you have conventions - use polymorphism instead (best), or, at least, check the type with is/as, for example:
if (this is Drived)
{
((Drived)this).SomeDrivedMethod();
}
Note that it breaks the OOP principles: a class shouldn't know about its drived classes.
Hope this helped you. Have a nice day!
Edit:
For your purpose, you can do one of the following:
Best - debug your code, see the call stack etc.
Worse - print the caller method name, instead of the object name. It's can be done using System.Runtime.CompilerServices.CallerMemberNameAttribute:
void Increment([System.Runtime.CompilerServices.CallerMemberName] string caller = null)
{
// Default value to `caller` is neccessary
// ...
Console.WriteLine("Caller: {0}", caller);
}
Note: the compiler fills the caller parameter, not in runtime.
Get object.GetHashCode() if you want to uniquely identify class object or provide name to class by using custom constructor.
Greeting fellow programmers!
I am currently studying software development (I started not a month ago) and I have a problem that needs a solution. Underneath you can find the code and as you can see, the method WriteNumber needs help. I need to write the code in a way that when I run the program, on the console screen the following two lines will be shown:
Hello World!
81
The Main method code cannot be changed and also I cannot add more methods to the class Calculator so the code needs to be done only within the WriteNumbers method. I have tried a lot of things but I am still grasping how everything works so any help is welcome! Thank you in advance for your time.
Namespace CalculatorTest
{
class Calculator
{
public static string WriteText (string input)
{
return "" + input;
}
public static string WriteNumber()
{
}
}
class Program
{
static void Main(string[] args)
{
string s = Calculator.WriteText("Hello World!");
Console.WriteLine(s);
string n = Calculator.WriteNumber(53 + 28);
Console.WriteLine(n);
Console.Read();
}
}
Not to do your homework for you to just be copied/pasted, hopefully I can give you some hints...
Notice how the method is being invoked:
Calculator.WriteNumber(53 + 28)
The 53 + 28 part happens first, then the result of that operation is passed to the method. That result, naturally, is 81. What's important about that is its type, which is an integer.
So, reasonably, the method signature needs to accept an int as a parameter. This would be done very similarly to how the other method accepts a string as a parameter:
public static string WriteText(string input)
What, then, does that method need to do with that input? Well, it's only a single value, so there aren't any calculations to be performed on it. It would appear that the method simply needs to return the value as a string. (It's your homework so you tell me, is that correct?)
This can be done with exactly two things:
Calling .ToString() on the value
Using the return keyword to return the result of that operation
(Note: The .ToString() operation does something very intuitive on value types, such as int or double or bool. As you progress into using reference types, you're going to find that it does something very different. Any time you have a custom class on which you want to call .ToString(), you'll need to override the .ToString() method on that class first.)
Please read David's answer, it's important that you make the effort to understand why this works the way it does. That being said:
public static string WriteNumber(int number)
{
return number.ToString();
}
Thank you all for your valuable input but special thanks to David because he showed where I made my error. I forgot that the two numbers in the main function will be summed up FIRST and THEN forwarded to the method in the class Calculator. After that got cleared up, it was easy to understand what to do (basically adjust the type of the input parameter to int).
namespace CalculatorTest
{
class Calculator
{
public static string WriteText (string input)
{
return "" + input;
}
public static string WriteNumber(int sumOfNumbers)
{
return "" + sumOfNumbers;
}
}
class Program
{
static void Main(string[] args)
{
string s = Calculator.WriteText("Hello World!");
Console.WriteLine(s);
string n = Calculator.WriteNumber(53 + 28);
Console.WriteLine(n);
Console.Read();
}
}
}
I have a public class, "CodeCompiler", which allows me to compile and run C# code at run-time. Just like IDEs work.
When I click the "button1" it creates code at run-time, compiles and executes.
My main Form1 contains a TextBox control called "textbox1". In order to make changes on that "textbox1" by runtime I made this button1_Click event.
But when I click it, it shows me a run-time error...
Compiler Errors :
Line 14,34 : An object reference is required for the non-static field, method, or property 'Compiling_CSharp_Code_at_Runtime.Form1.textBox1'
It showed me when I was editing the text data on that "textbox1". But if I will try to make changes about other property like "Size", "Location" then imagine what will happen!
using System;
using System.Text;
using Microsoft.CSharp;
using System.CodeDom.Compiler;
using System.Reflection;
namespace Compiling_CSharp_Code_at_Runtime
{
public class CodeCompiler
{
public CodeCompiler()
{
}
public object ExecuteCode(string code, string namespacename, string classname,
string functionname, bool isstatic,
string[] References1, params object[] args)
{
object returnval = null;
CompilerParameters compilerparams = new CompilerParameters();
for (int i = 0; i <= References1.GetUpperBound(0); i++)
{
compilerparams.ReferencedAssemblies.Add(References1[i]);
}
Assembly asm = BuildAssembly(code, compilerparams);
object instance = null;
Type type = null;
if (isstatic)
{
type = asm.GetType(namespacename + "." + classname);
}
else
{
instance = asm.CreateInstance(namespacename + "." + classname);
type = instance.GetType();
}
MethodInfo method = type.GetMethod(functionname);
returnval = method.Invoke(instance, args);
return returnval;
}
private Assembly BuildAssembly(string code, CompilerParameters compilerparams)
{
Microsoft.CSharp.CSharpCodeProvider provider = new CSharpCodeProvider();
ICodeCompiler compiler = provider.CreateCompiler();
compilerparams.GenerateExecutable = false;
compilerparams.GenerateInMemory = true;
CompilerResults results = compiler.CompileAssemblyFromSource(compilerparams, code);
if (results.Errors.HasErrors)
{
StringBuilder errors = new StringBuilder("Compiler Errors :\r\n");
foreach (CompilerError error in results.Errors )
{
errors.AppendFormat("Line {0},{1}\t: {2}\n", error.Line, error.Column, error.ErrorText);
}
throw new Exception(errors.ToString());
}
else
{
return results.CompiledAssembly;
}
}
}
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
CodeCompiler cc = new CodeCompiler();
string SourceCode1 = #"
using Compiling_CSharp_Code_at_Runtime;
using System;
using System.ComponentModel;
using System.Windows.Forms;
using System.Drawing;
namespace N1
{
public class C1
{
public static void F1(string st1, string st2)
{
Compiling_CSharp_Code_at_Runtime.Form1.textBox1.Text += ""This is a DEMO "" st1 + st2.ToUpper();
}
}
}";
string namespace1 = "N1", class1 = "C1", function1 = "F1";
bool IsStatic = true;
object o = cc.ExecuteCode(SourceCode1, namespace1, class1, function1, IsStatic, new string[] { "Compiling CSharp Code at Runtime.exe", "System.Windows.Forms.dll", "System.Drawing.dll", "System.ComponentModel.dll", "System.dll" }, "arg1", "arg2");
}
}
}
I found many problems related to this problem on this site where a suggestion was:
"It looks like I am calling a non static property from a static method.
I should either make the property static, or create an instance of Form1."
But even creation an instance of Form1 was difficult at runtime!
The problem appears to be that you're not passing reference to the Form1 on which you want code to be executed to CodeCompiler at all. The fact that you're calling it within your Form1 doesn't change anything - objects don't automatically learn anything about the object using them. (If they did, things would be a lot more complicated.)
The way you're accessing Form1 is also incorrect - you're using the typename (by the way, as a fully-qualified path which is pointless, because while the class C1 is not in the same namespace as Form1, you include Form1's namespace in the compiled code via using) to refer to a non-static member of the type. The instance member textBox1 of the type Form1 can be accessed only from some instance, but there's no logical way to access the Form1 object. What if you'd instantiated 10 of them? How would the decision be made which of those 10 to return to your call?
What you should do, if you want to continue down this path (and I'm not really sure why you're trying to mimic eval() in C# - you're throwing away a lot of the safety that makes C# nice and easy to work with), is pass a reference to the Form1 instance you want altered either in the constructor of CodeCompiler or in the ExecuteCode method. I think the latter would probably make more sense.
You should change your SourceCode1 so that it looks like this (this also fixes a typo in the original code, restoring a missing + character):
string SourceCode1 = #"
using Compiling_CSharp_Code_at_Runtime;
using System;
using System.ComponentModel;
using System.Windows.Forms;
using System.Drawing;
namespace N1
{
public class C1
{
public static void F1(string st1, string st2, Form1 formToExecuteOn)
{
formToExecuteOn.textBox1.Text +=
""This is a DEMO "" + st1 + st2.ToUpper();
}
}
}";
Then call the ExecuteCode() method like this:
object o = cc.ExecuteCode(SourceCode1, namespace1, class1, function1, IsStatic,
new string[] { "Compiling CSharp Code at Runtime.exe",
"System.Windows.Forms.dll", "System.Drawing.dll",
"System.ComponentModel.dll", "System.dll" },
"arg1", "arg2", this);
This will compile the code such that the Form1 instance to be used can be passed to the method when it's invoked. And the reference to that Form1 instance is provided in the argument list that is actually passed for the method invocation (i.e. the last argument, this)..
Granted, even if that works, it'll only allow you to execute code on Form1 objects. The greater point of this is that if you're going to go down this path, you need to be passing reference to anything you want altered to CodeCompiler somehow. I'm not sure whether object objectToChange would work instead of formToChange, and how much information the compiler is going to need about the object you're passing in order to execute code on it.
And once more, for feeling: you need a very, very unique use case to make any of this even remotely a good use of time or sanity. (You have to pass seven precisely-constructed objects, mostly strings, to ExecuteCode() every single time you want to run anything!)
I am currently studying C# and am trying to prepare for next weeks lessons which will be the introduction of classes and methods. To that end i have attempted to build a class called MaxBox which is meant to be a general utility class that I can store some general functions in like 'Displaying a String' or 'Play Again'. I've built my main file (Program) and my class file (MaxBox) and lines #23, #28 and #59 return the same general error 'An object reference is required for the non-static field, method, or property 'program.MaxBox.DisplayStr(string)'. #57 returns a similar error 'An object reference is required for the non-static field, method, or property 'program.MaxBox.PlayAgain()'
I'm a total newb really, and i'm wrestling with objects, I've done some research to get myself this far but I don't understand the language enough yet to be able to understand what the resources I've read are saying I guess to solve this error. Help and guidance is greatly appreciated. I'm still in my first weeks and really I know nothing.
Program:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading; // needed for close
using System.Threading.Tasks;
namespace a020_Breakcase_MeaningOfNames_C
{
class Program
{
public void Play()
{
/*
* Conditionals - Use switch/Case statement too:
* Evaluate user data (name)
* Return meaning of name evaluated
* OR
* Return 'Name not found' error message
* Say goodbye
*/
MaxBox.DisplayStr("What's in a name? Let's find out!");
Console.Write("\n\n");
do
{
MaxBox.DisplayStr("Enter Name: ");
string uName = Console.ReadLine().ToLower();
switch (uName)
{
case "doyle":
Console.WriteLine("Doyle means descendant of Dubhghalle");
break;
case "fiona":
Console.WriteLine("Fiona is considered to be a Latinised form of the Gaelic word fionn, meaning \"white\", \"fair\".");
break;
case "hunter":
Console.WriteLine("Hunter means to search with purpose");
break;
case "liam":
Console.WriteLine("This name is a short form of the Irish name Uilliam (William) which is now use independently as a given name. As a Hebrew name, Liam means \"my people; I have a nation\".");
break;
case "max":
Console.WriteLine("Short for of Maximilian, Maxwell, and the various name using it as a first syllable.");
break;
case "portia":
Console.WriteLine("It is of Latin origin. Feminine form of a Roman clan name. Portia was used by Shakespeare as the name of a clever, determined young heroine in \"The Merchant of Venice\" who disguises herself as a lawyer to save her husband's life.");
break;
default:
Console.WriteLine("I'm sorry but I don't know the meaning of the name " + uName + ".");
break;
}
} while (MaxBox.PlayAgain());
MaxBox.DisplayStr("C#eers!");
}
static void Main(string[] args)
{
Program myProgram = new Program();
myProgram.Play();
Console.Read();
}
}
}
My Class:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace a020_Breakcase_MeaningOfNames_C
{
class MaxBox
{
/*
* MaxBox is my general functions class
* Contains
* DisplayStr() - Display the string given
* PlayAgain() - If True, runs program again
*/
public String uName;
public String command;
public void DisplayStr(String StrTxt)
{ Console.Write(StrTxt); }
public Boolean PlayAgain()
{
Console.Write("\n\nDo you want to play again? (y)es or (n)o: ");
String command = Console.ReadLine().ToLower().Trim();
if (command == "y" || command == "yes") return true;
return false;
}
}
}
MaxBox's methods are not static, you need an instance of it.
MaxBox maxBox = new MaxBox();
at the beginning of your main class. Then
maxBox.DisplayStr(....)
also, just to get you thinking, you can replace:
if (command == "y" || command == "yes") return true;
return false;
with
return (command == "y" || command == "yes");
The methods PlayAgain and DisplayStr are instance methods on the type MaxBox. In order to call them you need an instance of MaxBox on which to call them. Right now you are trying to call them via the type name which only works for static methods
MaxBox.DisplayStr("hello world"); // wrong
MaxBox mb = new MaxBox();
mb.DisplayStr("hello world"); // right
It is possible to define methods such that you can invoke them from the type name. But doing so requires that they be marked as static
class MaxBox {
public static void DisplayStr2(string str){ ... }
}
MaxBox.DisplayStr2("hello world"); // right