ToString and string concatenation - unexpected behavior - c#

According to the internet when you do
String someString = "" + object1 + object2 + object3;
ToString() is called on each of the objects.
But this is not happening!
This code:
String a = "a" + foo;
String b = "b" + foo.ToString();
Console.WriteLine(a);
Console.WriteLine(b);
Prints:
a
b("key":"foo")
How is it possible?
I made Resharper full cleanup on whole project and it broke code in some place because it removed ToString() in such string concat!! Lost many hours..
Edit:
This problem happened in one of small libraries I was using. I cannot provide very short one-file code that will reproduce this but I have created small project with this library and uploaded to github:
https://github.com/Vistritium/ToStringCSObjectConcat
https://github.com/Vistritium/ToStringCSObjectConcat/blob/master/TestString/Program.cs
The library is 1178 lines long.

This can happen if you have provided an implicit operator converting your class to a string, for instance:
public class Foo
{
public string Key { get; set; }
public string Value { get; set; }
public static implicit operator string(Foo foo)
{
return foo == null ? string.Empty : foo.Value;
}
public override string ToString()
{
var str = string.Empty;
if (!string.IsNullOrEmpty(Key))
{
if (str.Length > 0)
str += ";";
str += ("Key=" + Key);
}
if (!string.IsNullOrEmpty(Value))
{
if (str.Length > 0)
str += ";";
str += ("Value=" + Value);
}
return str;
}
}
In that case:
string a = "a" + new Foo { Key = "foo", Value = "" };
string b = "b" + new Foo { Key = "foo", Value = "" }.ToString();
Debug.WriteLine(a); // Prints "a".
Debug.WriteLine(b); // Prints "bKey=foo
You could also get this effect if you have overloaded the + operator for string and Foo.
Update
From the C# Language Specification, 7.2.2 Operator overloading:
All unary and binary operators have predefined implementations that are automatically available in any expression. In addition to the predefined implementations, user-defined implementations can be introduced by including operator declarations in classes and structs (Section 10.9). User-defined operator implementations always take precedence over predefined operator implementations: Only when no applicable user-defined operator implementations exist will the predefined operator implementations be considered.
That's why the custom logic gets invoked in preference to the standard logic.

I just did this and it is working perfectly
private void button1_Click(object sender, EventArgs e)
{
var o = new x ();
string s = "ff" + o;
Console.WriteLine(s);
}
public class x {
public override string ToString()
{
return "This is string";
}
}
Prints
ffThis is string
Which tells me that you do something wrong. I mean, not as much that you do wrong as much as you expect something different than your objects produce in ToString

Related

Delete a string variable from Another String Variable in C#

I have a string variable operation_sequence. I'd like to remove another string variable job.Description from it.
For example, if I wanted to add job.Description to operation_sequence, I can do:
operation_sequence += job.Description;
and this works. But if I wanted to remove job.Description from operation_sequence, the following code does not work:
operation_sequence -= job.Description;
What's the best way to remove job.Description from operation_sequence?
You could easily use String.Replace():
String HelloWord = "Hello World!";
String NewWord= HelloWord.Replace("o","");
NewWord will be=Hell Wrld!
We can't use -= or - for string. But we can implement it for our own string class.
Solution 1
public class MyString
{
public string Value { get; private set; }
public MyString(string value)
{
Value = value;
}
public static MyString operator +(MyString left, MyString right)
{
return new MyString(left.Value + right.Value);
}
public static MyString operator -(MyString left, MyString right)
{
if (string.IsNullOrEmpty(left.Value))
return left;
if (string.IsNullOrEmpty(right.Value))
return left;
if (left.Value.EndsWith(right.Value))
{
int startIndex = left.Value.Length - right.Value.Length;
string result = left.Value.Substring(0, startIndex);
return new MyString(result);
}
return left;
}
public static implicit operator string(MyString value) => value.Value;
public static implicit operator MyString(string value) => new MyString(value);
}
As you know we can't overload -= and +=(See this). Therefore I overloaded - and +. Now we can use our class like this:
MyString s1 = "This is ";
MyString s2 = "just a test";
string s3 = s1 + s2; // s3 = "This is just a test"
string s4 = s3 - s2; // s4 = "This is "
Because of public static implicit operator MyString(string value) => new MyString(value) we can have something like MyString s1 = "test". It implicitly converts string to MyString.
Because of public static implicit operator string(MyString value) => value.Value we can have something like string s3 = MyString("test"). It implicitly converts MyString to string.
In the - operator we checked if the left operand ends with the right one, we removed it.
Solution 2
And also we can simply use an extension method like this:
public static class StringExtension
{
public static string MinusString(this string baseString, string minusString)
{
if (string.IsNullOrEmpty(baseString))
return baseString;
if (string.IsNullOrEmpty(minusString))
return baseString;
if (baseString.EndsWith(minusString))
{
int startIndex = baseString.Length - minusString.Length;
string result = baseString.Substring(0, startIndex);
return new MyString(result);
}
return baseString;
}
}
and now we can use it like this:
string s = "This is just a test";
string s3 = s.MinusString("a test"); // s3 = "This is just "
s3 = s3.MinusString("just "); // s3 = "This is "
Solution suggested by Klaus Gütter worked for me, which is defining operation_sequence as a List and converting it to a string only after manipulation, using String.Join.
private string operation_sequence;
List<string> ops = new List<string>(3);
// Add item to List:
ops.Add(job.Description);
// or Remove item from List:
ops.Remove(job.Description);
//then update operation_sequence string with values from List<string>:
operation_sequence = String.Join(", ", ops);

How to pass a class as optional parameter to a method?

I have searched around here for similar problems, but couldn't find a solution for my problem.
MyClass holds several data and does some type casting between different types.
How can i avoid this Error:
A value of type 'string' cannot be used as default parameter
because there are no standard conversions to type Program.MyClass?
I have tried Func and declared multiple function overload to be able to pass multiple argument and handle default parameter. There should be a better way to achieve this. Hopefully you could help.
To clarify my problem i have made this code:
using System;
public class Program
{
public class MyClass {
public string Value { get; set; }
public MyClass()
{
Value = "";
}
public MyClass(string s)
{
Value = s;
}
public override string ToString()
{
return this.Value;
}
}
// Causes CS1750
// A value of type 'string' cannot be used as default parameter
// because there are no standard conversions to type 'Program.MyClass'
public static string test2(string a, MyClass b = " with default text")
{
return a + b;
}
public static string test(string a, string b = " with default text")
{
return a + b;
}
public static void Main()
{
Console.WriteLine(test("test1"));
Console.WriteLine(test("test1", " with my text"));
}
}
That's not quite possible. As the error message states, you require a standard conversion: https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/language-specification/conversions#standard-conversions
All we can do is to define an implicit conversion operator for the class: https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/operators/user-defined-conversion-operators
In your case, it would be something like:
public static implicit operator MyClass(string val) => new MyClass(val);
And replace your test method with something like this:
public static string test(string a, MyClass b = null)
{
b = b ?? " with default text";
return a + b;
}
Also note that both your test methods have the same signature if only one argument is provided, so the compiler won't know which one to use, remove the default value for the 2nd test method.
use null for default value, and replace it with default value inside method:
public static string test2(string a, MyClass b = null)
{
if (b == null) return a + " with default text";
return a + b.Value;
}
Add an implicit conversion operator between string and MyClass
public class MyClass
{
public string Value { get; set; }
public MyClass() : this(string.Empty) { }
public MyClass(string s)
{
Value = s;
}
public override string ToString() => this.Value;
public static implicit operator string(MyClass item) => item.Value;
public static implicit operator MyClass(string value) => new MyClass(value)l;
}
You should change 2 steps (In case apply for whole class)
1. Initial default value on Constructor
public MyClass()
{
Value = " with default text";
}
2. Change default params of the method
public static string test(string a, MyClass b)
{
return a + b;
}
BTW, This post is helpful for you.
UPDATED: Set default value for only within function
The code above just suit in case applying for whole class.
If you wanna set default value for only within function, You can try the code below
public static string test2(string a, MyClass b = null)
{
var defaultValue = " with default text";
return a + (b == null ? defaultValue : b.Value);
}

Overriding implicit operators in C#

I use a framework which exposes an abstract class called Value. Through operator overloading, it's possible to assign almost anything to this class's objects, and it works like a charm:
Value a = "hello";
Value b = 1;
Value c = true;
Value d = 3.14;
(Note that this is the only way to create instances of Value. There are no public/protected ways to assign values to instances, other than the overloaded operators.)
Right now, I want to override the implicit operator Value(string input) function, so that it XML-sanitizes any string before assigning it.
I have tried inheriting this class and overriding the operator, but have not found a way to feed the sanitized string into the base class's operator function. The following obviously doesn't work:
public override static implicit operator XmlValue(string input)
{
string output = sanitize(input);
XmlValue rv = null;
((Value)rv) = output; // this is not possible
return rv;
}
Is there a way to achieve this? Or alternatively, am I perhaps overthinking the problem and is there a better solution for what I want to do? In any case, I'd like to avoid having to sanitize each and every string before assigning it to a Value; this would be way too error prone.
FYI: the Value class is part of the Cottle framework.
The important point is that you cannot "override" operators, because they are static. You can instead define a new operator in your derived class, then make the assignment using a variable of your derived type (so that the compiler knows that it needs to call the operator of the derived class).
Look at this example:
using System;
class Value {
public string StringValue {
get;
private set;
}
protected Value(string str) {
StringValue = str;
}
public static implicit operator Value(string input) {
return new Value(input);
}
}
class XmlValue : Value {
protected XmlValue(string str) : base(str) {
}
public static implicit operator XmlValue(string input) {
// using "ToUpperInvariant" instead of sanitize
return new XmlValue(input.ToUpperInvariant());
}
}
class Program {
static void Main(string[] args) {
Value v1 = "test";
Console.WriteLine(v1.StringValue); // "test"
XmlValue v2 = "test";
Console.WriteLine(v2.StringValue); // "TEST"
}
}
After checking your comment, I think that the example below is more related to the real situation you are facing.
However, as fun as this operators overloading might be, I think that in this case you should definitely opt for the simpler and more readable solution of sanitizing every input before assignment.
using System;
abstract class Value {
public string StringValue {
get;
protected set;
}
public static implicit operator Value(string input) {
return new StringValue(input);
}
}
class StringValue : Value {
public StringValue(string str) {
StringValue = str;
}
}
class Xml {
string _value;
public Xml(string value) {
_value = value;
}
public static implicit operator Xml(string input) {
return new Xml(input.ToUpperInvariant());
}
public static implicit operator Value(Xml xml) {
Value ret = xml._value;
return ret;
}
}
class Program {
static void Main(string[] args) {
// this works with the cast operators...
Value v1 = (Xml)"test";
Console.WriteLine(v1.StringValue); // "TEST"
// ...but I would definitely go for this:
Value v2 = sanitize("test");
}
}

How to overload '-' operator to copy strings

The question here is
Write a program to construct a class "MyString" which has one string and length of that string as its data members. now overload '-' operator to copy the string into another string.
I'm not understanding how to do this..I've written a code which when i'm trying to use in main its showing the following error:
Error 1 Operator '-' cannot be applied to operands of type 'string' and 'string'
my code is:
public class MyString
{
public string s="SILADITYA";
//public string this[string s]{ get; set; }
public static string operator -(string s1, MyString m)
{
s1 = String.Copy(m.s);
return s1;
}
}
class Program
{
static void Main(string[] args)
{
MyString m = new MyString();
string s1 = s1 - m.s;
}
}
please tell me how can I overload this opoerator
Your code is correct just make this change while calling it from Main
string s1 = string.Empty;
s1 = s1 - m;
It was failing since your operator overload expects a string and MyString parameters and you were supplying String and String

Help with mathematic operands in class (c#)

public class Racional<T>
{
private T nominator;
private T denominator;
public T Nominator
{
get { return nominator; }
set { nominator = value; }
}
public T Denominator
{
get { return denominator; }
set { denominator = value; }
}
public Racional(T nominator, T denominator)
{
this.nominator = nominator;
this.denominator = denominator;
}
public static Racional<int> operator *(Racional<int> a, Racional<int> b)
{
return ((int)(a.nominator + b.nominator, a.denominator + b.denominator));
}
public override string ToString()
{
return "(" + this.nominator + " " + this.denominator + ")";
}
}
I'm interested in this part :
public static Racional<int> operator *(Racional<int> a, Racional<int> b)
{
return ((int)(a.nominator + b.nominator, a.denominator + b.denominator));
}
What's wrong:
One of the parameters of a binary operator must be the containing type
How I can normaly code this part for mathematic operations?
The reason your code doesn't compile is explained by the compiler error. The containing type is a generic type definition, and a generic type constructed from such a type is not considered to be the same type.
I have a few questions:
Why must the Rational type be generic? A rational number is defined as a number that can be expressed as the quotient / fraction of two integers (where the denominator is not 0). Why not make the type non-generic and simply use int throughout? Or do you intend that the type be used for other integral types such as long and BigInteger? In that case, consider using something like Aliostad's suggestion if you want some code-sharing mechanism.
Why do you want the product of two rational numbers to be the equal to the sum of their numerators over the sum of their denominators? That doesn't make sense to me.
In any case, you appear to want to be able to 'generically' add two instances of an 'addable' type. Unfortunately, there currently isn't any way to express a 'has a suitable addition operator' constraint in C#.
Method #1: One workaround for this in C# 4 is to use the dynamic type to give you the desired "virtual operator" semantics.
public static Racional<T> operator *(Racional<T> a, Racional<T> b)
{
var nominatorSum = (dynamic)a.Nominator + b.Nominator;
var denominatorSum = (dynamic)a.Denominator + b.Denominator;
return new Racional<T>(nominatorSum, denominatorSum);
}
The operator will throw if the type doesn't have a suitable addition operator.
Method #2: Another (more efficient) way is to use expression-trees.
First, create and cache a delegate that can perform the addition by compiling the appropriate expression:
private readonly static Func<T, T, T> Adder;
static Racional()
{
var firstOperand = Expression.Parameter(typeof(T), "x");
var secondOperand = Expression.Parameter(typeof(T), "y");
var body = Expression.Add(firstOperand, secondOperand);
Adder = Expression.Lambda<Func<T, T, T>>
(body, firstOperand, secondOperand).Compile();
}
(The static constructor will throw if the type doesn't have a suitable addition operator.)
Then employ it in the operator:
public static Racional<T> operator *(Racional<T> a, Racional<T> b)
{
var nominatorSum = Adder(a.Nominator, b.Nominator);
var denominatorSum = Adder(a.Denominator, b.Denominator);
return new Racional<T>(nominatorSum, denominatorSum);
}
The issue here is you are defining an operator for Racional<int> in the class Racional<T>. This is not possible. The types are not the same, you can only define operator for Racional<T>.
Generics cannot express generalization of operators since they are defined only for a certain types. Solution is to create a class and inherit from Racional<int>:
public class IntRacional : Racional<int>
{
public static Racional<int> operator +(IntRacional a, IntRacional b)
{
return new Racional<int>()
{
Nominator = a.Nominator + b.Nominator,
Denominator = a.Denominator + b.Denominator
};
}
}
To solve your issue, you need to provide conversion functions from T to some type where operator+ is defined and vice versa. Assuming Int64 is big enough in most cases, this can be done this way:
public class Racional<T>
{
private T nominator;
private T denominator;
static Converter<T,Int64> T_to_Int64;
static Converter<Int64,T> Int64_to_T;
public static void InitConverters(Converter<T,Int64> t2int, Converter<Int64,T> int2t )
{
T_to_Int64 = t2int;
Int64_to_T = int2t;
}
public T Nominator
{
get { return nominator; }
set { nominator = value; }
}
public T Denominator
{
get { return denominator; }
set { denominator = value; }
}
public Racional(T nominator, T denominator)
{
this.nominator = nominator;
this.denominator = denominator;
}
public static Racional<T> operator *(Racional<T> a, Racional<T> b)
{
return new Racional<T>(
Int64_to_T(T_to_Int64(a.nominator) + T_to_Int64(b.nominator)),
Int64_to_T(T_to_Int64(a.denominator) + T_to_Int64(b.denominator)));
}
// By the way, should this not be * instead of + ???
//
// public static Racional<T> operator *(Racional<T> a, Racional<T> b)
// {
// return new Racional<T>(
// Int64_to_T(T_to_Int64(a.nominator) * T_to_Int64(b.nominator)),
// Int64_to_T(T_to_Int64(a.denominator) * T_to_Int64(b.denominator)));
// }
public override string ToString()
{
return "(" + this.nominator + " " + this.denominator + ")";
}
}
Of course, this has the drawback that you must provide the initialization of those converters somewhere at the program start, should look like this:
Racional<int>.InitConverters(x => (Int64)x, y => (int)y);
In a real program, you may know which possible replacements for T you are going to use. So one can provide those 3 or 4 calls in a static constructor like this:
public static Racional()
{
Racional<int>.InitConverters(x => (Int64)x, y => (int)y);
Racional<short>.InitConverters(x => (Int64)x, y => (short)y);
Racional<Int64>.InitConverters(x => (Int64)x, y => (Int64)y);
}
should be sufficient in most cases. Note that this converter initialization is repeated for all 3 types 3 times again, re-initializing the conversion functions multiple times again. In practice this should not make any trouble.

Categories