I'm sure this is a stupid question, but why does the following code not call the explicit operator for the cast on the child class MyBool?
public class DataType
{
public static explicit operator bool(DataType D)
{
return false;
}
public static explicit operator DataType(bool B)
{
return new DataType();
}
}
public class MyBool : DataType
{
public bool Value;
public MyBool()
{
Value = false;
}
public static explicit operator bool(MyBool B)
{
return B.Value;
}
public static explicit operator MyBool(bool B)
{
return new MyBool() { Value = B };
}
}
then:
List<DataType> Types = new List<DataType>();
Types.Add(new MyBool() { Value = true });
Types.Add(new MyBool() { Value = false });
foreach (DataType T in Types)
{
bool Value = (bool)T;
MessageBox.Show(Value.ToString());
}
Produces the output: false, false
Is my only option to write functions on each class to take the place of the explicit operator functions?
why does the following code not call the explicit operator for the cast on the child class MyBool?
Because the operator functions are static, hence also non-virtual and thus their target is resolved at compile time rather than runtime. This is the expected behaviour.
If you want to have polymorphic conversion operators you can call virtual functions inside the operators:
public abstract class DataType
{
public static explicit operator bool(DataType D)
{
return D.DoCastToBool();
}
public static explicit operator DataType(bool B)
{
// We haven’t got an instance of our class here.
// You can use a factory method pattern to emulate virtual constructors.
}
protected abstract bool DoCastToBool();
}
Operators are overloaded rather than overridden - in other words, the choice about which implementation to use is made at compile-time. The compiler only knows about T as DataType, so it calls the operator in DataType.
One option would be to remove the operator from MyBool, but add a virtual method in DataType, allowing for polymorphic behaviour:
public class DataType
{
public static explicit operator bool(DataType D)
{
// TODO: Decide how you want to handle null references
return D.ToBoolean();
}
protected virtual bool ToBoolean()
{
return false;
}
}
public class MyBool : DataType
{
// ...
protected override bool ToBoolean()
{
return Value;
}
}
Note that this won't work for the conversion from bool to a DataType, as in that case we don't have any information about which subtype of DataType you actually want to create.
(Side-note: your code would be easier to follow if you used the normal .NET naming conventions.)
Here's a garbage solution for you:
replace: bool Value = (bool)T;
with: bool Value = (bool)(T as MyBool);
Related
I'm writing an abstract wrapper for enum in C # (I want something like enum in Vala). My code is:
public abstract class Wraper<T, TE>
where T : Wraper<T, TE>, new()
{
public TE Value;
public static implicit operator T(TE value)
{
return new T() { Value = value };
}
public static implicit operator TE(T value)
{
return value.Value;
}
}
I want to do with something like this:
public enum EFoo { A, B, C, D, E};
public class Foo : Wraper<Foo, EFoo>
{
public bool IsBla
{
get { return Value == EFoo.A || Value == EFoo.E; }
}
}
...
Foo foo = EFoo.A;
bool bla = foo.IsBla;
But the code does not compile because C # does not allow both generic parameter,. When compile reports an error:
User-defined conversion must convert to or from the enclosing type
On line
public static implicit operator T(TE value)
Is there any work around or in C# is not so simple?
The implicit operator must convert either from or to the class you are defining it in. Since you are trying to define it in the abstract base class, it can only convert from or to that class.
The line Foo foo = EFoo.A; does not work because you can't define that conversion in your abstract class, you can only define it in your Foo class.
If you changed your code, as I did below, to convert from/to the base class, the implicit conversions work but you don't get the result you want. Wraper<Foo,EFoo> foo2 = EFoo.A; works because it can be defined in the base class.
Your best bet is probably to use the initializer syntax when creating your foo Foo foo = new Foo { Value = EFoo.A }; or to create some generic conversion functions.
public abstract class Wraper<T, TE>
where T : Wraper<T, TE>, new()
{
public TE Value;
public static implicit operator TE(Wraper<T, TE> value)
{
return value.Value;
}
public static implicit operator Wraper<T, TE>(TE value)
{
return new T { Value = value };
}
}
public enum EFoo
{
A,
B,
C,
D,
E
}
public class Foo : Wraper<Foo, EFoo>
{
public bool IsBla
{
get
{
return Value == EFoo.A || Value == EFoo.E;
}
}
}
I recently wrote a couple of structs in .NET, to which I then added implicit conversion operators
Example:
public struct Alpha
{
internal string value;
public static implicit operator Alpha(Beta b)
{
return new Alpha() { value = b.value };
}
public static implicit operator Beta(Alpha a)
{
return new Beta() { value = a.value };
}
}
public struct Beta
{
internal string value;
public static implicit operator Alpha(Beta b)
{
return new Alpha() { value = b.value };
}
public static implicit operator Beta(Alpha a)
{
return new Beta() { value = a.value };
}
}
Test:
Alpha a = default(Alpha);
Beta b = a;
// Ambiguous user defined conversions 'Alpha.implicit operator Beta(Alpha)' and 'Beta.implicit operator Beta(Alpha)' when converting from 'Alpha' to 'Beta'
I would like to know what the rules / best practices are surrounding implicit conversion in C#?
Note to self: My gut feeling is that types should not return objects of another type through implicit conversion? i.e. Beta should not return Alpha via implicit conversion, and vice-versa, however, Beta should return Beta, and Alpha should return Alpha
Example (fixed):
public struct Alpha
{
internal string value;
public static implicit operator Alpha(Beta b)
{
return new Alpha() { value = b.value };
}
}
public struct Beta
{
internal string value;
public static implicit operator Beta(Alpha a)
{
return new Beta() { value = a.value };
}
}
Is my assumption correct?
You have a Alpha(Beta x) defined in both classes, thus it is ambiguous which one should be used. Allow each class to handle only the conversion to itself. In other words, struct Alpha implements Alpha(Beta b) because it best knows how to create an instance of itself. Also, I would consider implementing explicit conversions instead of implicit. It can sometimes cause bugs or unexpected conversions accidentally, and when dealing with complex classes are often "lossy" conversions.
public struct Alpha
{
internal string value;
public static implicit operator Alpha(Beta b)
{
return new Alpha() { value = b.value };
}
}
public struct Beta
{
internal string value;
public static implicit operator Beta(Alpha a)
{
return new Beta() { value = a.value };
}
}
The only time you'd likely implement "both ways" in a single class, is if the other class has no knowledge of your new class. This is the more common scenario when you want to support conversion to-from a pre-existing class/struct such as supporting conversion to-from a framework type:
public struct Alpha
{
internal string value;
public static implicit operator Alpha(string b)
{
return new Alpha() { value = b };
}
public static implicit operator string(Alpha a)
{
return a.value;
}
}
No, your assumpion is not correct (even though you wrote working code thanks to it). The problem in your code is that you have defined the same conversion operators in both classes, this is why they are ambiguous; the compiler cannot decide which one to use.
You can read more in section 6.4.3 (Evaluation of user-defined conversions) of the C# 4.0 Language Specification.
I have a generic class. It has 2 constructors. Those are widely used in my organization's codebase.
class MyClass<T> {
MyClass() { ... }
MyClass(T defaultValue) { ... }
}
I would like to add some functionality but keep backward-compatible. So I would like to introduce a new boolean optional parameter to each constructor:
class MyClass<T> {
MyClass(bool someFlag = false) { ... }
MyClass(T defaultValue, bool someFlag = false) { ... }
}
However, I already have a heap of usages out there in which T is boolean and a default value is passed:
class Usage {
MyClass<bool> Booly = new MyClass<bool>(false);
}
Now, according to the laws of overload preference - the compiler is tying all such constructor usages to the overload accepting someFlag, since typed methods "know better". While making perfect sense in most cases, this is obviously breaking my backward-compatibility.
My question is simple: Is there a language feature available for me to override the default laws of overload preference, and define the old generic overload as the preferred one, so that I don't have to change all such usages?
Of course, a drawback of this design is that whenever I would want to call the first overload (with only the someFlag parameter) - I would have to specify a named parameter as per C# 4 specifications.
Suggestions for other designs are also welcome, but please try to answer my question first :).
In general? No.
A specific... "workaround"... which might be acceptable in your case? Make the optional parameter a bool?, not a bool.
new MyClass<bool>(false) will call your defaultValue overload.
new MyClass<bool>(someFlag: false) will call the other overload.
That said, if you have any existing new MyClass<bool?>(false) calls, this will change them over instead.
You can overcome this by creating an class specifically for making your flags not be bools:
public struct FakeBool
{
private readonly bool val;
private FakeBool(bool val) { this.val = val; }
public static implicit operator bool(FakeBool f) { return f.val; }
public static implicit operator FakeBool(bool f) { return new FakeBool(f); }
}
public MyClass(FakeBool someFlag = default(FakeBool)) { ... }
public MyClass(T defaultValue, FakeBool someFlag = default(FakeBool)) { ... }
var b2 = new MyClass<bool>(true); // calls two-argument constructor
var b1 = new MyClass<bool>(someFlag: true); // calls one-argument constructor
but this is getting silly. (Also, I can't figure out how to get a default value of true - any ideas, anyone?)
Assuming you can have an Initialize() type method that you can call from each constructor, your best bet is to have three constructors:
MyClass() { Initialize(null, false); }
MyClass(T default, bool someFlag = false) { Initialize(default, someFlag); }
MyClass(bool someFlag)
{
if (typeof(T) == typeof(bool)) Initialize(someFlag, false);
else Initialize(null, someFlag);
}
private Initialize(T default, bool someFlag)
{
// Do whatever
}
I'm troubleshooting a problem that I have recreated in a solution here.
The issue is that I am using some custom types that can implicitly cast from string to themselves. One of the custom types inherits from the other.
public class CustomType
{
public string InnerString { get; protected set; }
public CustomType(string s)
{
InnerString = s;
}
#region Operator Overloads
public static implicit operator CustomType(string s)
{
if (s == null)
throw new ArgumentNullException();
return new CustomType(s);
}
public static implicit operator string(CustomType value)
{
if (value == null)
return null;
return value.InnerString;
}
#endregion
}
public class SubCustomType : CustomType
{
public SubCustomType(string s)
: base(s)
{
// Nada
}
#region Operator Overloads
public static implicit operator SubCustomType(string s)
{
if (s == null)
throw new ArgumentNullException();
return new SubCustomType(s);
}
public static implicit operator string(SubCustomType value)
{
if (value == null)
return null;
return value.InnerString;
}
#endregion
}
In another generic class, I rely upon the fact that the base custom type can implicitly cast from string to itself. (The cast occurs at the line (T)this.Rtf. .Rtf is a string.) (The generic class is in my case a subclass of RichTextBox, since that's what I was using when I ran into this problem.)
public class CustomRichTextBox<T> : Forms.RichTextBox
where T : CustomType
{
public object GetValue()
{
/// This line throws:
/// InvalidCastException
/// Unable to cast object of type 'TestCustomTypesCast.CustomType' to type 'TestCustomTypesCast.SubCustomType'.
return (T)this.Rtf;
}
}
public class SubCustomRichTextBox : CustomRichTextBox<SubCustomType>
{
}
When I use SubCustomRichTextBox (an instance of the generic class that has as type argument the SUB custom type), I get an InvalidCastException at the line where I cast to T in GetValue. What I think is going on is that in order for the compiler to be okay with the fact that I am using T to cast from string, it is looking at CustomType and seeing its cast overload. But even when I use a subclass of CustomType as the actual type argument, the compiler still looks to SubCustomType.CustomType(string s) to perform the cast, and not at the correct SubCustomType.SubCustomType(string s) method.
Can anyone point me in the direction of fixing this problem? I want to use the generic class because it would allow me to reuse the same code. If I can't use generics, then I'll need to duplicate code in several subclasses of CustomRichTextBox<T>. Thanks.
It's going to be hard because the operator overload is static, and you're essentially trying to get a virtual behaviour.
Try this:
public class CustomRichTextBox<T> : Forms.RichTextBox
where T : CustomType, new()
{
public object GetValue()
{
T t = new T();
t.InnerString = this.Rtf;
return t;
}
}
Note I've added new() to the type constraint. I also had to make InnerString public settable.
As an aside, you coule make the return type of GetValue() be T. That might be a nicer API.
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
}