Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 3 years ago.
Improve this question
I have come across a problem upon viewing some tutorials on C# since I just started learning this language recently. I had a problem where once I had reversed a string I had to make use of new string in order to store its actual value in a different varible.
Why is the use of 'new string()' needed? In different programming languages I have never come across the need of using 'new string()'. Thanks in advance :)
//C#
char[] reversedName = name.ToCharArray();
Array.Reverse(reversedName);
string result = new string(reversedName);
String is a class like other classes in any Object oriented programming language and we can create object of it using new keyword like we would do for creating object of any type.
In your specific scenario above you have a char array and String class have a constructor overload which take char[] as input and create a String. So you call the constructor using new String.
So what is happening is you said to create an object of type string using char[] which is provided in the constructor of it.
You can - as in any other of your mentioned languages - of course also use something like this:
string m = "Hello World".
However your reversedName is an array of char, which is not convertible to string as is. So the following won´t work:
string myString = "Hello World".ToCharArray();
because ToCharArray - as the name suggests - returns char[], not string and there´s no conversion between the two.
That´s why you need to create a new string using the constructor that accepts an array of char.
The new-Keyword is used to create a new instance of your class.
If you want to assign one value of one type to another type you have to convert it in some way.
There are multiple ways:
Call a Constructor which accepts your input (You did this, because there is a constructor for string which accepts char[])
Use a Cast (No Cast available from char[] to string)
Use a Convert-Method (No available for converting values to string as far a I know)
Here an example-class which implements explicit and implicit casts (Which System.String does not):
class MyString
{
private string stringValues;
// Constructors
public MyString(char[] charArray) { stringValues = new string(charArray); }
public MyString(string str) { stringValues = str; }
public MyString() { }
// ToString for writing to console
public override string ToString() { return stringValues; }
// Operator to concat "MyStrings"
public static MyString operator +(MyString a, MyString b) { return new MyString(a.ToString() + a.ToString()); }
// Implicit Cast-operator string to MyString
public static implicit operator MyString(string str) { return new MyString(str); }
// Explicit Cast-operator char-array to MyString
public static explicit operator MyString(char[] str) { return new MyString(str); }
}
internal static void Main(string[] args)
{
MyString tmp = new MyString("Initialize by constructor with parameter string");
Console.WriteLine(tmp);
tmp = new MyString("Initialize by constructor with parameter char-array".ToCharArray());
Console.WriteLine(tmp);
tmp = new MyString("x") + new MyString("+") + new MyString("y");
Console.WriteLine("Use of '+ operator'" + tmp);
tmp = "Initialize by creating string and using implicit cast for strings";
Console.WriteLine(tmp);
tmp = (MyString)("Initialize by creating char-array and using explicit cast for strings".ToCharArray());
Console.WriteLine(tmp);
}
Related
... when I try this in C#:
string reversedName;
reversedName = name.ToCharArray().Reverse().ToArray();
But not when I try this:
string reversedName = new string (name.ToCharArray().Reverse().ToArray());
? And when I try adding chaining a To.String() to the end of the first method, the Runtime doesn't throw an exception but returns: System.Char[]
I'm looking for an explanation on why the compiler seems to not be able to implicitly convert char[] to string:
* except when, apparently, calling new string,
* even when we chain the ToString() function to the end there.
When you try
string reversedName = new string (name.ToCharArray().Reverse().ToArray());
you are creating string with its constructor. As you can see, first parameter is array of chars:
https://msdn.microsoft.com/en-us/library/ms131424(v=vs.110).aspx
But here
reversedName = name.ToCharArray().Reverse().ToArray();
you are returning an array (with .ToArray() at the end), which is obviously not assignable to variable of type string.
Calling ToString() on array will print its type System.Char[], as you already noticed.
The ToString() on an Char Array object will return System.Char[] because it's the default and expected behavior. The compiler cannot assume that you want to join every char into one string, and return that string.
The correct way is to use new string(char[]).
You can also always use a Extension class to add a extension method.
public static class Extensions
{
public static string ConvertToString(this char[] array)
{
return new string(array);
}
}
Usage:
string s = array.ConvertToString();
This question already has answers here:
Why covariance and contravariance do not support value type
(4 answers)
Closed 7 years ago.
So I have a method in my code where one of the parameters is a IEnumerable<object>. For clarity purposes, that will be the only parameter for the example. I was originally calling it with a variable that was a List<string>, but then realized I only needed those to be chars and changed the signature of the variable to List<char>. Then I received an error in my program saying:
Cannot convert source type 'System.Collections.Generic.List<char>'
to target type 'System.Collections.Generic.IEnumerable<object>'.
In code:
// This is the example of my method
private void ConversionExample(IEnumerable<object> objs)
{
...
}
// here is another method that will call this method.
private void OtherMethod()
{
var strings = new List<string>();
// This call works fine
ConversionExample(strings);
var chars = new List<char>();
// This will blow up
ConverstionExample(chars);
}
The only reason that I could possibly think of as to why the first will work, but the second won't is because a List<char>() is convertible to a string? I don't really think that would be it, but that's the only long-shot guess that I can make about why this doesn't work.
Generic argument covariance doesn't support value types; it only works when the generic argument is a reference type.
You can either make ConversionExample generic and accept an IEnumerable<T> rather than an IEnumerable<object>, or use Cast<object> to convert the List<char> to an IEnumerable<object>.
This would be my solution:
// This is the example of my method
private void ConversionExample<T>(IEnumerable<T> objs)
{
...
}
// here is another method that will call this method.
private void OtherMethod()
{
var strings = new List<string>();
// This call works fine
ConversionExample<string>(strings);
var chars = new List<char>();
// This should work now
ConversionExample<char>(chars);
}
I probably missing something but as I understand string and String are aliases as explained in difference-between-string-and-string so string is just an object!
Now what I don't understand is how the following code initialize new object of String?
string s="Hello World"
Can I do this trick for regular objects?
If you are compiling them in your code.. they are compile time constants.. i.e. code explicitly references them from your compiled binary, which is of course loaded in memory at runtime..
If you construct them at runtime.. like from char array, I would guess that CLR has the necessary implementation for doing so. For example - look at following code from http://referencesource.microsoft.com/#mscorlib/system/string.cs,97ccd50b20126543
[System.Security.SecuritySafeCritical] // auto-generated
private static String ConcatArray(String[] values, int totalLength) {
String result = FastAllocateString(totalLength);
int currPos=0;
for (int i=0; i<values.Length; i++) {
Contract.Assert((currPos <= totalLength - values[i].Length),
"[String.ConcatArray](currPos <= totalLength - values[i].Length)");
FillStringChecked(result, currPos, values[i]);
currPos+=values[i].Length;
}
return result;
}
[System.Security.SecurityCritical] // auto-generated
[ResourceExposure(ResourceScope.None)]
[MethodImplAttribute(MethodImplOptions.InternalCall)]
internal extern static String FastAllocateString(int length);
Essentially strings get special treatment in the language, and although they are objects (immutable), you are right in your understanding that they are not instantiated with new operator in traditional sense. i.e. you don't do what you said in your comment String s=new String("Hello World"); because if you think about it, the new is redundant, because you have already defined your string in double quotes as a string literal.
And hence while you could use implicit operator, to convert a string to a given type.. It is not the same trick. The trick in case of strings is the native support from CLR.
EDIT:
Here is another proof.. There is a special IL OpCode to load strings.
OpCodes.Ldstr
"Pushes a new object reference to a string literal stored in the metadata."
If you'll look at your compiled code, you'd see ldstr opcode being used to load strings, instead of newobj opcode.
As mentioned by #KirkWoll, from Using Conversion Operators you could use an implicit operator
Something like
public class FOO
{
private string _foo;
public static implicit operator FOO(string foo)
{
FOO f = new FOO {_foo = foo};
return f;
}
}
and then calling it
FOO bar = "TADA";
This question already has answers here:
Convert a string to an enum in C#
(29 answers)
Closed 8 years ago.
I'm reading file content and take string at exact location like this
string fileContentMessage = File.ReadAllText(filename).Substring(411, 3);
Output will always be either Ok or Err
On the other side I have MyObject which have ContentEnum like this
public class MyObject
{
public enum ContentEnum { Ok = 1, Err = 2 };
public ContentEnum Content { get; set; }
}
Now, on the client side I want to use code like this (to cast my string fileContentMessage to Content property)
string fileContentMessage = File.ReadAllText(filename).Substring(411, 3);
MyObject myObj = new MyObject ()
{
Content = /// ///,
};
Use Enum.Parse().
var content = (ContentEnum)Enum.Parse(typeof(ContentEnum), fileContentMessage);
As an extra, you can take the Enum.Parse answers already provided and put them in an easy-to-use static method in a helper class.
public static T ParseEnum<T>(string value)
{
return (T)Enum.Parse(typeof(T), value, ignoreCase: true);
}
And use it like so:
{
Content = ParseEnum<ContentEnum>(fileContentMessage);
};
Especially helpful if you have lots of (different) Enums to parse.
.NET 4.0+ has a generic Enum.TryParse
ContentEnum content;
Enum.TryParse(fileContentMessage, out content);
Have a look at using something like
Enum.TryParse
Converts the string representation of the name or numeric value of one
or more enumerated constants to an equivalent enumerated object. A
parameter specifies whether the operation is case-sensitive. The
return value indicates whether the conversion succeeded.
or
Enum.Parse
Converts the string representation of the name or numeric value of one
or more enumerated constants to an equivalent enumerated object.
I'm new to Extension Methods and exploring what they can do.
Is it possible for the calling object to be assigned the output without a specific assignment?
Here is a simple example to explain:
public static string ExtensionTest(this string input)
{
return input + " Extended!";
}
In the following examples ...
var foo = "Hello World!";
var foo2 = foo.ExtensionTest(); // foo2 = "Hello World! Extended!"
foo.ExtensionTest(); // foo = "Hello World!"
foo = foo.ExtensionTest(); // foo = "Hello World! Extended!"
... is there any way to get foo.ExtensionTest() to result in "Hello World! Extended!" without specifically assigning foo = foo.ExtensionTest()
No, but the reason that will not work has to do with the immutability of strings, and nothing to do with extension methods.
If instead you had a class:
public class SomeClass
{
public int Value {get; set;}
}
And an extension method:
public static void DoIt(this SomeClass someClass)
{
someClass.Value++;
}
Would have the effect of:
var someClass = new SomeClass{ Value = 1 };
someClass.DoIt();
Console.WriteLine(someClass.Value); //prints "2"
The closest you could get to this (which would be weird) would be to accept an out parameter and use that as the return value:
public static void ExtensionTest(this string input, out string output)
{
output = input + " Extended!";
}
Example:
string foo = "Hello World!";
foo.ExtensionTest(out foo);
The funny thing about that is, while it more closely resembles what you're asking about, it's actually slightly more to type.
To be clear: I don't recommend this, unless it's really important to you to make this sort of method call. The probability of another developer uttering "WTF?" upon seeing it has got to be something like 100%.
What you are seeing is due to strings being immutable.
In any case, you will have to do some sort of assignment if you want the object to change.
The 'this' parameter is passed by value, not by reference. So no, you can't modify the variable in the calling program that is aliased by 'this' in your extension method.
No. Strings in .NET are immutable. All public String methods return new instance of String too.
To assign the new value to your variable inside the extension method, you'd need a ref modifyer on the parameter, which the C# compiler does not permit on extension methods (and it would be a bad idea anyway). It's better to make it clear you're changing the variable.
Use the faster StringBuilder for mutable strings and as pointed out the ref or out keyword. StringBuilder is basically an improved linked-list for strings.
Immutable strings were a design decision to allow close behavior to the C language and many other languages.
string str = "foo";
str += "bar"; // str will be free for garbage collection,
//creating a new string object.
//Note: not entirely true in later C# versions.
StringBuilder sb = new StringBuild();
sb.Append("foo");
sb.Append("bar"); // appends object references to a linked list.
See also:
string is immutable and stringbuilder is mutable
http://en.wikipedia.org/wiki/Linked_list