How to overload '-' operator to copy strings - c#

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

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");
}
}

ToString and string concatenation - unexpected behavior

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

How to convert string type to user defined custom type

I have a string value that needs to be converted into my user defined custom type. how to do this, please help me.
public class ItemMaster
{
public static ItemMaster loadFromReader(string oReader)
{
return oReader;//here i am unable to convert into ItemMaster type
}
}
Depending on your type there are two ways that you could do it.
The first is adding a constructor to your type that takes a String parameter.
public YourCustomType(string data) {
// use data to populate the fields of your object
}
The second is adding a static Parse method.
public static YourCustomType Parse(string input) {
// parse the string into the parameters you need
return new YourCustomType(some, parameters);
}
Convert.ChangeType() method may help you.
string sAge = "23";
int iAge = (int)Convert.ChangeType(sAge, typeof(int));
string sDate = "01.01.2010";
DateTime dDate = (DateTime)Convert.ChangeType(sDate, typeof(DateTime));
Create a Parse method on your User Defined Custom type:
public class MyCustomType
{
public int A { get; private set; }
public int B { get; private set; }
public static MyCustomType Parse(string s)
{
// Manipulate s and construct a new instance of MyCustomType
var vals = s.Split(new char[] { '|' })
.Select(i => int.Parse(i))
.ToArray();
if(vals.Length != 2)
throw new FormatException("Invalid format.");
return new MyCustomType { A = vals[0], B = vals[1] };
}
}
Granted, the example provided is extremely simple but it at least will get you started.
First you need to define a format that your type will follow when being converted to a string.
A simple example is a social security number. You can easily describe it as a regular expression.
\d{3}-\d{2}-\d{4}
After that you simple need to reverse the process. The convention is to define a Parse method and a TryParse method for your type. The difference being that TryParse will not throw an exception.
public static SSN Parse(string input)
public static bool TryParse(string input, out SSN result)
Now the process you follow to actually parse the input string can be as complex or as simple as you wish. Typically you would tokenize the input string and perform syntactic validation. (EX: Can a dash go here?)
number
dash
number
dash
number
It really depends on how much work you want to put into it. Here is a basic example of how you might tokenize a string.
private static IEnumerable<Token> Tokenize(string input)
{
var startIndex = 0;
var endIndex = 0;
while (endIndex < input.Length)
{
if (char.IsDigit(input[endIndex]))
{
while (char.IsDigit(input[++endIndex]));
var value = input.SubString(startIndex, endIndex - startIndex);
yield return new Token(value, TokenType.Number);
}
else if (input[endIndex] == '-')
{
yield return new Token("-", TokenType.Dash);
}
else
{
yield return new Token(input[endIndex].ToString(), TokenType.Error);
}
startIndex = ++endIndex;
}
}
For the actual conversion, we would need to see the class structure for. The skeleton for this would look as follows however:
class MyType
{
// Implementation ...
public MyType ConvertFromString(string value)
{
// Convert this from the string into your type
}
}

Categories