Question: Can C# interfaces contain operators?
From searching, the answer I have found is no.
For example, C# interface cannot contain operators
However, in Andrew Troelsen's book "Pro C# 5.0 and the .Net 4.5 framework" he makes the following statement
Alas, operator constraints are not supported under the current version of C#. However, it is possible
(albeit it requires a bit more work) to achieve the desired effect by defining an interface that supports
these operators (C# interfaces can define operators!) and then specifying an interface constraint of the
generic class.
The sentence in bold is what puzzles me. Indeed, when I try the following
using System;
interface MathOps<T> where T : class
{
static T operator+(T a, T b);
}
class MyClass : MathOps<MyClass>
{
int x;
public MyClass(int n = 0)
{
x = n;
}
public static MyClass operator+(MyClass a, MyClass b)
{
return new MyClass(a.x + b.x);
}
}
class Program
{
static void Add<T>(ref T a, ref T b) where T : class, MathOps<T>
{
return a + b;
}
static void Main(string[] args)
{
}
}
The compiler throws the following back at me
error CS0567: Interfaces cannot contain operators
So the case kinda seems settled. But why does Mr Troelsen write the way he does? Am i missing/misinterpreting something?
Thanks.
One key to remember is that, as far as I know, it's not so much that an interface cannot define operators (though that is true) but that interfaces cannot define statics, which is frustrating but also logical.
Related
I just found out that it is possible to use the keyword var as a class name:
public class var // no problem here
{
}
Now if I overload the implicit cast operator I can use my class in an interesting manner:
namespace MyApp
{
class Program
{
static void Main(string[] args)
{
var x = 1; // var is of type MyApp.var
}
}
public class var
{
public implicit operator var(int i)
{
return new var();
}
}
}
In such scenario, is it still possible to somehow make the compiler infer the types? This blog entry states that it is not possible (go to the paragraph starting with "Or, another example."), but maybe something changed since 2009?
To make it short
It is not possible to use implicit variable declaration if you name a class var.
Can't the C# design team just disallow naming classes like that to avoid confusing code?
No, because that might break some code written before the new meaning of var was introduced in the language. All legacy code with var as class names would not compile anymore. And I read lately that backwards compatibility is very important for the C# designer team.
I have a class that overrides the addition operator twice. One that takes the type parameter and one that takes a double:
public class A<T>
{
public A() { }
public static A<T> operator +(A<T> a, T t)
{
Console.WriteLine("Generic add called.");
return new A<T>(); // return to keep the compiler happy
}
public static A<T> operator +(A<T> a, double d)
{
Console.WriteLine("Double add called.");
return new A<T>(); // return to keep the compiler happy
}
}
When the class is parameterized by the int type, it behaves as expected:
A<int> aInt = new A<int>();
var test = aInt + 3;
// -> Generic add called.
test = aInt + 3.0;
// -> Double add called.
But when parameterized by the double type, the non-generic add is called:
A<double> aDouble = new A<double>();
var otherTest = aDouble + 3.0;
// -> Double add called.
Assuming this behavior is the norm, I know which will be called. The non-generic override will be preferred. That said...
Will the non-generic method be always be preferred in the event of a collision?
All of the above code is available, runnable in your browser, here
EDIT: This question is related, but it's asking about generic methods, not classes. He gives this code:
class A
{
public static void MyMethod<T>(T myVal) { }
public static void MyMethod(int myVal) { }
}
which does not apply to my usage examples. Distinguishing between a.MyMethod(3) and a.MyMethod<int>(3) is obvious - one is generic and one is not.
The more specific method will be chosen, but that construction is a bad idea because it is technically unspecified behaviour.
To quote #EricLippert, substituting the code snippets for the ones from my question:
But the situation with [aDouble + 3.0] is far worse. The CLR rules make this sort of situation "implementation defined behaviour" and therefore any old thing can happen. Technically, the CLR could refuse to verify a program that constructs type [A<double>]. Or it could crash. In point of fact it does neither; it does the best it can with the bad situation.
Are there any examples of this sort of type construction causing truly implementation-defined behaviour?
Yes. See these articles for details:
http://blogs.msdn.com/b/ericlippert/archive/2006/04/05/odious-ambiguous-overloads-part-one.aspx
http://blogs.msdn.com/b/ericlippert/archive/2006/04/06/odious-ambiguous-overloads-part-two.aspx
Simple answering yes. The compiler assume that because you have treated by hand a particular type parameter, that means that it has some special logic for you. That's why the second operator is called. To say further, operators are nothing more than static methods that accepts some parameters. For your case it's a binary operator so the static method has two parameters.
I'm reading about extension methods, and monkeying around with them
to see how they work, and I tried this:
namespace clunk {
public static class oog {
public static int doubleMe(this int x) {
return 2 * x;
}
}
class Program {
static void Main() {
Console.WriteLine(5.doubleMe());
}
}
}
and it worked as expected, successfully extending int with the doubleMe method, printing 10.
Next, being an old C guy, I wondered if I could do this:
namespace clunk {
public static class BoolLikeC {
public static bool operator true(this int i) { return i != 0; }
public static bool operator false(this int i) { return i == 0; }
}
class Program {
static void Main() {
if ( 7 ) {
Console.WriteLine("7 is so true");
}
}
}
}
I would think if the former would work, then the latter ought to work to make it such that
an int used in a boolean context would call the extension method on int, check to see that
7 is not equal to 0, and return true. But instead, the compiler doesn't even like the
later code, and puts the red squiggly lines under the two this's and says "Type expected".
Why shouldn't this work?
Very clever! A nice attempt, but regrettably we did not implement "extension everything", just extension methods.
We considered implementing extension properties, extension operators, extension events, extension constructors, extension interfaces, you name it, but most of them were not compelling enough to make it into C# 4 or the upcoming version of C#. We got as far as designing a syntax for the sort of thing you mention. We got rather farther on extension properties; we almost got extension properties into C# 4 but it ended up not working out. The sad story is here.
http://blogs.msdn.com/b/ericlippert/archive/2009/10/05/why-no-extension-properties.aspx
So, long story short, no such feature, but we'll consider it for hypothetical future releases of the language.
You can of course make a "ToBool()" extension method on int if you really do like the retro C convention that non-zero-means-true.
Extension methods are exactly that—methods.
You cannot make extension operators or properties.
Had that been possible, it would result in very hard-to-read code.
If you aren't familiar with the code base, it's almost impossible to figure out what if (7) means.
As others have said, there's no such thing as extension operators in C#.
The closest you can get, running the risk of facilitating lots of nasty bugs down the line, would be with implicit conversion operators on a custom "bridge" type:
// this works
BoolLikeC evil = 7;
if (evil) Console.WriteLine("7 is so true");
// and this works too
if ((BoolLikeC)7) Console.WriteLine("7 is so true");
// but this still won't work, thankfully
if (7) Console.WriteLine("7 is so true");
// and neither will this
if ((bool)7) Console.WriteLine("7 is so true");
// ...
public struct BoolLikeC
{
private readonly int _value;
public int Value { get { return _value; } }
public BoolLikeC(int value)
{
_value = value;
}
public static implicit operator bool(BoolLikeC x)
{
return (x.Value != 0);
}
public static implicit operator BoolLikeC(int x)
{
return new BoolLikeC(x);
}
}
Unfortunately you cannot introduce new operators, or implement support for existing operators, on types, through extension methods.
Basically, what you want to do cannot be done.
The only way to introduce new operators is to put them in one of the involved types. For binary operators you can put them in your own type, provided your type is one of the two, for unary types you need to put the operator inside the type itself.
Since you can't extend an int in any way, you can't do it.
Console.WriteLine(5.doubleMe());
is equivalent to
Console.WriteLine(oog.doubleMe(5));
Given that, you can see why if ( 7 ) doesn't work.
Extension methods are nothing more than syntax.
As a side note since it is syntax you can call extension methods on null variables because it translates to a normal method call, and methods can take null parameters.
Unfortunately you cannot use extension methods to add operators, and implicit type conversion in C# is implemented as an operator.
In the first instance you are writing an extension method - e.g. extending the functionality of the int data type. In the second code set, you are trying to override the bool operators. These are two totally different things.
This question came to my mind while I
am reading the post Why doesn't C#
support multiple inheritance?
from MSDN Blog.
At first look at the following code:
using System;
using System.Collections.Generic;
using System.Text;
namespace ConsoleApplication1
{
class A
{
int num;
public A()
{
num = 0;
}
public A(int x)
{
num = x;
}
public override int GetHashCode()
{
return num + base.GetHashCode();
}
}
class B : A
{
int num;
public B()
{
num = 0;
}
public B(int x)
{
num = x;
}
public override int GetHashCode()
{
return num + base.GetHashCode();
}
}
class Program
{
static void Main(string[] args)
{
A a = new A();
B b = new B();
Console.Write(a.GetHashCode() + " " + b.GetHashCode());
Console.Read();
}
}
}
Object class is the ultimate base class of all classes. So it is the base class of A and B both in my program and also make A as a base class of B. So B has now two base class, one is A and another is Object. I override one method GetHashCode() of Object Class in class A and B both. But in class B, base.GetHashCode() method returns the return value of GetHashCode() method of class A. But I want this value from Object class. How can I get that?
B has only one base class, and that is A. A has one base class, and that is object. There is no multiple inheritance; object is only inherited by classes that don’t already inherit from something else.
If you still think you need to call object.GetHashCode(), there is a very hacky workaround to do this in the question How to invoke (non virtually) the original implementation of a virtual method?.
You could write a protected instance method in class A that exposes GetHashCode() from Object. Then call that protected method in class B.
No Class B merely has one base class, class A.
To understand, class A really should be written as:
class A : Object
But since that is required, it can be left off.
This may help you: http://itpian.com/Coding/5191-cant-v-have-Multiple-Inheritances-in-C-sharp---------.aspx
Yes, this doesn't relate to multiple inheritance at all (incidentally, I miss private inheritance more than multiple inheritance). This question is also quite a horrible thing to think about.
If you have control of class A, then fine:
class A
{
/*elide the stuff you already have*/
protected int GetBaseHashCode()
{
return base.GetHashCode();
}
}
class A : B
{
/*elide stuff already in example*/
public override int GetHashCode()
{
return num + GetBaseHashCode();
}
}
If you do not:
public class B : A
{
private static readonly DynamicMethod GRANDPARENT_GET_HASH_CODE;
static B()
{
MethodInfo gpGHC = typeof(object).GetMethod("GetHashCode", BindingFlags.Public | BindingFlags.Instance);
GRANDPARENT_GET_HASH_CODE = new DynamicMethod("grandParentGHC", typeof(int), new Type[] { typeof(object) }, typeof(object));
ILGenerator il = GRANDPARENT_GET_HASH_CODE.GetILGenerator();
il.Emit(OpCodes.Ldarg, 0);
il.EmitCall(OpCodes.Call, gpGHC, null);
il.Emit(OpCodes.Ret);
}
private int num;
public B()
{
num = 0;
}
public B(int x)
{
num = x;
}
public override int GetHashCode()
{
return num + (int)GRANDPARENT_GET_HASH_CODE.Invoke(null, new object[]{this});
}
}
Frankly, I would put that code in the category of "let us never speak of it again". I assume this is relating to some more general principle, since the hashcodes here are useless anyway, but I'm not sure what that more general principle is. Certainly it can sometimes be annoying when something is hidden from deriving classes we want to get at, but it can be much worse when the opposite happens.
Back in the days of VB6, coders in that language would often have to do rather nasty stuff involving getting the memory address of the v-table used for virtual call lookup, altering the memory protection, and then tweaking the bytes stored there by hand, because in "protecting" users from implementation details they kept some vital things away from them (you could not create enumerators without this technique, only pass on those for other objects).
Thank goodness we are not "protected" to that extent in C#. If I ever have to write code like the answer I gave above for a real project, I'm going to need a few drinks to recover later that evening.
Getting a hash of the base Object class is irrelevant to the purpose of the method. The whole point of GetHashCode() is to generate a unique (as possible) identity value based on the specific type and state of the object.
The GetHashCode() method uses a default hashing algorithm that can be used to determine instance identity and uniqueness, though uniqueness is not guaranteed. The default algorithm uses the state of the object to generate the hash.
More information: http://msdn.microsoft.com/en-us/library/system.object.gethashcode.aspx
I'm afraid you are mixing normal inheritance with multiple inheritance. Multiple inheritance meand that you have 3 classes A is subclass of B and C but neither B is subclass of C nor C is subclass of B.
Normal inheritance does allow chaining like A is subclass of B which is subclass of C. If you call method it can walk through the classes and check which method to call (in reality it does not check classes one by one). Here B is subclass of A which is subclass of Object. Object happens to have (virtual) method GetHashCode - by overloading it in subclass. The Object method is hidden and (without tricks) cannot be used.
You should consider an alternative to calling Object.GetHashCode(). Here's why (from MSDN Library):
The default implementation of the
GetHashCode method does not guarantee
unique return values for different
objects. Furthermore, the .NET
Framework does not guarantee the
default implementation of the
GetHashCode method, and the value it
returns will be the same between
different versions of the .NET
Framework. Consequently, the default
implementation of this method must not
be used as a unique object identifier
for hashing purposes.
This question already has answers here:
Anyone know a good workaround for the lack of an enum generic constraint?
(12 answers)
Closed 9 years ago.
Update: See the bottom of this question for a C# workaround.
Hi there,
Consider the following extension method:
public static bool HasFlags<T>(this T value, T flags)
where T : System.Enum
{
// ...
}
This will, as you may know, throw an error at compile-time, since a class is not normally allowed to inherit from System.Enum. The problem is that any enumeration specified using the enum keyword does in fact inherit from System.Enum, so the above code would be the ideal way to limit an extension method to enumerations only.
Now the obvious work-around here is to use Enum instead of T, but then you lose the benefits of generic types:
MyEnum e;
e.HasFlags(MyOtherEnum.DoFunkyStuff);
The above code would throw a compile-time error using generic types, while it can only throw a runtime error using the Enum type (if I implement it to do so.)
Are there any compiler options that can be used to turn off the constraint check, or is there some other nifty way to do this?
Before it is suggested, I would like to say that I will not be using where T : struct or some such, since then you'd be able to do weird stuff like 123.HasFlags(456).
I'm stumped as to why this error exists at all... It's the same problem you'd get using where T : System.Object, but for that you have where T : class... Why is there no where T : enum?
C# workaround
Jon Skeet has started work on a library that compiles classes with a constraint to an IEnumConstraint, which is then replaced with System.Enum post-build. This is, I believe, the closest one can get to working around this issue at this time.
See:
Code project: http://code.google.com/p/unconstrained-melody/
Blog entry: http://msmvps.com/blogs/jon_skeet/archive/2009/09/10/generic-constraints-for-enums-and-delegates.aspx
If this workaround is unfeasible, you will have to write your library as C++/CLI code, which does not limit what can be used for generic type constraints (see the code in my answer below.)
EDIT: A library is now available supporting this via ildasm/ilasm: UnconstrainedMelody.
Members of the C# team have previously said they'd like to be able to support where T : Enum and where T : Delegate, but that it's never been a high enough priority. (I'm not sure what the reasoning is for having the restriction in the first place, admittedly...)
The most practical workaround in C# is:
public static bool HasFlags<T>(this T value, T flags) where T : struct
{
if (!(value is Enum))
{
throw new ArgumentException();
}
// ...
}
That loses compile-time checking for the "enum-ness" but keeps the check that you're using the same type in both places. It has the execution-time penalty of the check as well, of course. You can avoid that execution-time penalty after the first call by using a generic nested type for the implementation which throws the exception in a static constructor:
public static bool HasFlags<T>(this T value, T flags) where T : struct
{
if (!(value is Enum))
{
throw new ArgumentException();
}
return EnumHelper<T>.HasFlags(value, flags);
}
private class EnumHelper<T> where T : struct
{
static EnumHelper()
{
if (!typeof(Enum).IsAssignableFrom(typeof(T))
{
throw new InvalidOperationException(); // Or something similar
}
}
internal static HasFlags(T value, T flags)
{
...
}
}
As Greco mentions, you could write the method in C++/CLI and then reference the class library from C# as another option.
Actually, it is possible, with an ugly trick.
However, it cannot be used for extension methods.
public abstract class Enums<Temp> where Temp : class {
public static TEnum Parse<TEnum>(string name) where TEnum : struct, Temp {
return (TEnum)Enum.Parse(typeof(TEnum), name);
}
}
public abstract class Enums : Enums<Enum> { }
Enums.Parse<DateTimeKind>("Local")
If you want to, you can give Enums<Temp> a private constructor and a public nested abstract inherited class with Temp as Enum, to prevent inherited versions for non-enums.
I couldn't resist having a go at the C++ work-around, and since I got it to work I figured I'd share it with the rest of ya!
Here's the C++ code (my C++ is very rusty so please point out any errors, in particular how the arguments are defined):
#include "stdafx.h"
using namespace System;
using namespace System::Runtime::CompilerServices;
namespace Blixt
{
namespace Utilities
{
[Extension]
public ref class EnumUtility abstract sealed
{
public:
generic <typename T> where T : value class, Enum
[Extension]
static bool HasFlags(T value, T flags)
{
__int64 mask = Convert::ToInt64(flags);
return (Convert::ToInt64(value) & mask) == mask;
}
};
}
}
And the C# code for testing (console application):
using System;
using Blixt.Utilities;
namespace Blixt.Playground
{
[Flags]
public enum Colors : byte
{
Black = 0,
Red = 1,
Green = 2,
Blue = 4
}
[Flags]
public enum Tastes : byte
{
Nothing = 0,
Sour = 1,
Sweet = 2,
Bitter = 4,
Salty = 8
}
class Program
{
static void Main(string[] args)
{
Colors c = Colors.Blue | Colors.Red;
Console.WriteLine("Green and blue? {0}", c.HasFlags(Colors.Green | Colors.Red));
Console.WriteLine("Blue? {0}", c.HasFlags(Colors.Blue));
Console.WriteLine("Green? {0}", c.HasFlags(Colors.Green));
Console.WriteLine("Red and blue? {0}", c.HasFlags(Colors.Red | Colors.Blue));
// Compilation error:
//Console.WriteLine("Sour? {0}", c.HasFlags(Tastes.Sour));
Console.WriteLine("Press any key to exit...");
Console.ReadKey(true);
}
}
}
You can achieve this using IL Weaving and ExtraConstraints
Allows you to write this code
public static bool HasFlags<[EnumConstraint] T>(this T value, T flags)
{
// ...
}
What gets compiled
public static bool HasFlags<T>(this T value, T flags)
where T : System.Enum
{
// ...
}