C# custom variables - c#

I was experimenting with making a custom variables but got stuck.
I'm still new to C# so it's only expected for me to not know what's happening, I guess..
struct MyCustomStringVariable
{
public static implicit operator MyCustomStringVariable(string input)
{
return input;
}
}
class Program
{
static MyCustomStringVariable myCustomString = "This is a string!";
static void Main(string[] args)
{
Console.WriteLine(myCustomString);
Console.ReadLine();
}
}
The following exception is thrown
System.StackOverflowException: 'Exception of type 'System.StackOverflowException' was thrown.'

This is because the code is stuck in an infinit loop. Your implicit operator will call itself because it returns the original input string which does not throw an exception because of the defined operator.
public static implicit operator MyCustomStringVariable(string input)
{
return input; // returning string type will call this method again
}
should be
public static implicit operator MyCustomStringVariable(string input)
{
// and use input somewhere on the returned type
return new MyCustomStringVariable();
}
That said there is probably no reason for you to define a type named MyCustomStringVariable but that is hard to tell because you never share the code for this or how you intend to use it.
My final goal is to visualize the process of making a string variable in my head so that I can better understand the concept behind it.
I am not sure how your custom struct or its implicit operator fit in with this goal. Why not just use the type string?
static string myCustomString = "This is a string!";

It's because the implicit operator is called recursively. You'll need to implement your structure as so, encapsulating your string variable somehow.
struct MyCustomStringVariable
{
private string value;
public MyCustomStringVariable(string input)
{
value = input;
}
public static implicit operator MyCustomStringVariable(string input)
{
return new MyCustomStringVariable(input);
}
public string GetValue()
{
return value;
}
}
Then, calling it like
Console.WriteLine(myCustomString.GetValue());
You can refer to the documentation here.

Related

How to use implicit casting in expression tree c#?

I have simplified program, which uses expressions:
public class Program
{
public static IEnumerable<char> foo1()
{
// For some reason I cannot change result type
return new char[] { 's', '1' };
}
public static string foo2()
{
// For some reason I cannot change result type
return "s1";
}
static void Main()
{
Expression cond = Expression.Condition(Expression.Constant(true),
Expression.Call(typeof(Program).GetMethod("foo1")),
Expression.Call(typeof(Program).GetMethod("foo2")));
}
}
During execution I have following error
Argument types do not match.
As I understood c# does not use implicit type casting. How can I solve this problem?
When building expressions it's not going to add in implicit conversions for you. You need to specifically indicate that you want to apply the conversion operator(s) using Expression.Convert.
Expression cond = Expression.Condition(Expression.Constant(true),
Expression.Call(typeof(Program).GetMethod("foo1")),
Expression.Convert(Expression.Call(typeof(Program).GetMethod("foo2")), typeof(IEnumerable<char>)));

Anyone know how I can get FCL style initialisation syntax for c# types?

Instead of writing
int i = new int();
i = 7;
One can write
int i = 7;
Is there a way I can get that style of initialisation for my own types?
MyType mt = xyz;
The closest you can come is by creating implicit conversions on your type. For example:
public class Unit
{
public static implicit operator Unit( string val )
{
return Unit.Parse( val );
}
public static Unit Parse( string unitString )
{
// parsing magic goes here
}
}
This would enable you to do something like this:
Unit width = "150px";
var width = Unit.Parse("150px"); // equivalent to previous line
Note that you cannot introduce new syntax; this would be impossible to implement:
Unit width = 150px;
since 150px does not represent a valid value type.
Note that implicit casting can get you into trouble in weird ways so don't over do it. Support implicit casting only to and from types that you're really going to need.
Alternatively, if you're using C# compiler 3.5 or up you can also use inline initialization which is more verbose but also more explicit:
Unit with = new { Value=150, UnitType=Units.Pixel };
For the specific example in your comment you could add an implicit conversion operator to the type.
Note that doing this is generally not recommended because it makes your code less readable. For example, something like String2 s2 = new String2("yo") is completely explicit about what is happening; not so with something like String2 s2 = "yo".
String2 s2 = "yo";
// ...
public sealed class String2
{
public readonly string _value;
public string Value { get { return _value; } }
public String2(string value)
{
_value = value;
}
public override string ToString()
{
return Value;
}
public static implicit operator String2(string value)
{
return new String2(value);
}
}
You can do it through implicit cast operators.
Here's an article that describes the concept:
http://www.codeproject.com/KB/cs/Csharp_implicit_operator.aspx
short answer is "no you can't". You're always going to hide a new somewhere.
In your specific case you could do some trick with implicit conversions like this:
class String2 {
private readonly string WrappedString;
public String2(string wrappedString) {
this.WrappedString = "my modified " + wrappedString ;
}
public override string ToString() {
return this.WrappedString;
}
// the "magic" is here: the string you assign to String2 gets implicitly
// converted to a String2
public static implicit operator String2(string wrappedString) {
return new String2(wrappedString);
}
}
that enables you to do:
String2 test = "test";
Console.WriteLine(test.ToString()); // writes: "my modified test" to the Console
but you get the "new" hidden in the implicit conversion anyway.
Another approach which may be more general and lands you not too far from the syntax you want is through extension methods:
static class StringExtensions {
public static String2 ToString2(this string that) {return new String2(that);}
}
with that in scope, you can do this:
var test2="anothertest".ToString2();

Is it possible to cast string into my own type?

public class Currency{
private Code {get;set;}
public Currency(string code){
this.Code = code;
}
//more methods here
}
I want to be able to make my object castable
string curr = "USD";
Currency myType = (Currency)curr;
I know that I can do it with the contructor, but I have usecase where I need to cast without initializing the object...
I also believe that ill need a function like FromString() to do it
Thanks.
Yes, just add an explicit cast operator:
public class Currency {
private readonly string code;
public string Code { get { return this.code; } }
public Currency(string code) {
this.code = code;
}
//more methods here
public static explicit operator Currency(string code) {
return new Currency(code);
}
}
Now you can say:
string curr = "USD";
Currency myType = (Currency)curr;
Add this method to your Currency class:
public static explicit operator Currency(String input)
{
return new Currency(input);
}
And call it like this:
Currency cur = (Currency)"USD";
If you create your own cast-operators for your type, you can make this possible.
check out the implicit and explicit keywords.
(in this case, I'd prefer an explicit cast).
I believe this operator does what you want (as part of your Currency class):
public static explicit operator Currency(stringvalue){
return new Currency(value);
}

Can I create accessors on structs to automatically convert to/from other datatypes?

is it possible to do something like the following:
struct test
{
this
{
get { /*do something*/ }
set { /*do something*/ }
}
}
so that if somebody tried to do this,
test tt = new test();
string asd = tt; // intercept this and then return something else
Conceptually, what you want to do here is in fact possible within .NET and C#, but you're barking up the wrong tree with regards to syntax. It seems like an implicit conversion operator would be the solution here,
Example:
struct Foo
{
public static implicit operator string(Foo value)
{
// Return string that represents the given instance.
}
public static implicit operator Foo(string value)
{
// Return instance of type Foo for given string value.
}
}
This allows you to assign and return strings (or any other type) to/from objects of your custom type (Foo here).
var foo = new Foo();
foo = "foobar";
var string = foo; // "foobar"
The two implicit conversion operators don't have to be symmetric of course, though it's usually advisable.
Note: There are also explicit conversion operators, but I think you're more after implicit operators.
You can define implicit and explicit conversion operators to and from your custom type.
public static implicit operator string(test value)
{
return "something else";
}
Expanding on MikeP's answer you want something like:
public static implicit operator Test( string value )
{
//custom conversion routine
}
or
public static explicit operator Test( string value )
{
//custom conversion routine
}

Using string constants in implicit conversion

Consider the following code:
public class TextType {
public TextType(String text) {
underlyingString = text;
}
public static implicit operator String(TextType text) {
return text.underlyingString;
}
private String underlyingString;
}
TextType text = new TextType("Something");
String str = text; // This is OK.
But I want to be able do the following, if possible.
TextType textFromStringConstant = "SomeOtherText";
I can't extend the String class with the TextType implicit operator overload, but is there any way to assign a literal string to another class (which is handled by a method or something)?
String is a reference type so when they developed C# they obviously had to use some way to get a string literal to the class. I just hope it's not hardcoded into the language.
public static implicit operator TextType(String text) {
return new TextType(text);
}
Add
public static implicit operator TextType(string content) {
return new TextType(content);
}
to your class? :)

Categories