TL;DR: Can I somehow create an algorithm that can use different functionality in the inner loop, and still get that "functionality" inlined, without resorting to copy/paste or if/else statements?
I am trying to create an algorithm that basically looks like this:
for(var i=0; i<big; i++) {
for(var j=0; j<big2; j++) {
// ... processing
var x = SomeFunc(a, b, c);
// ... more processing
}
}
I want the algorithm to be run for a number of possible functions (SomeFunc above), each called a large number of times per run. Each SomeFunc function is very simple (usually an arithmetic expression).
Now, to get acceptable performance out of this algorithm, it is imperative that SomeFunc is inlined. However I fail to get the function inlined while still allowing for multiple functions.
I realize this means that the algorithm function has to be JITted multiple times, but I was hoping that a construct like this would work:
interface ISomeFunc {
int SomeFunc(int a, int b, int c);
}
private sealed class SomeFunc1 : ISomeFunc {
public int SomeFunc(int a, int b, int c) {
return ....;
}
}
private static void RunMyGenericAlgo<T>(T func) where T : ISomeFunc
{
for ... for ..
x = func.SomeFunc(a, b, c);
}
But it appears that the function call is not inlined since func above is called via the interface and not via the sealed class.
I also tried the obvious approach:
abstract class MyAlgo {
protected abstract int SomeFunc(int a, int b, int c);
public void Run() {
// as RunMyGenericAlgo above
}
}
sealed class MyAlgoSomeFunc1 : MyAlgo {
protected override int SomeFunc(int a, int b, int c) {...}
}
and it did not inline either.
This program will however inline as desired (and runs about 50% faster):
class MyAlgo {
int SomeFunc(int a, int b, int c) {...}
public void Run() {
// as above
}
}
EDIT: To clarify, I also investigated using the MethodImpl attribute with AggressiveInlining, and it did not seem to help.
Is what I'm trying even possible in C# or do I have to copy/paste my algorithm for each implementation of my inner function?
To allow a method to be inlined, the implementation must be constant (e.g. not dependant on variables). So any form of a virtual/abstract/interface/delegate call is by definition a call that can never be inlined.
Therefore, the only way is to have a nonvirtual method call, or just paste the code in there.
There are some exceptions to this rule. For example, the JVM designers have the problem of all the Java methods being virtual by default, they have virtual call inlining. This will do something like:
//calling obj.MyVirtCall();
if (obj.Type == MyCommonType) {
//inlined code for MyCommonType.MyVirtCall();
} else {
obj.MyVirtCall();
}
Edit:
You could used T4 templates to generate C# code for each override of Run in your algorithm example, not requiring duplicate code, however it could make the maintenance slightly more complex, having to also maintain a T4 template instead of just C# code.
Related
Given
class Either<A, B> {
public Either(A x) {}
public Either(B x) {}
}
How to disambiguate between the two constructors when the two type parameters are the same?
For example, this line:
var e = new Either<string, string>("");
Fails with:
The call is ambiguous between the following methods or properties: 'Program.Either.Either(A)' and 'Program.Either.Either(B)'
I know if I had given the parameters different names (e.g. A a and B b instead of just x), I could use named parameters to disambiguate (e.g. new Either<string, string>(a: "")). But I'm interested in knowing how to solve this without changing the definition of Either.
Edit:
You can write a couple of smart constructors, but I'm interested in knowing if the Either's constructors can be called directly without ambiguity. (Or if there are other "tricks" besides this one).
static Either<A, B> Left<A, B>(A x) {
return new Either<A, B>(x);
}
static Either<A, B> Right<A, B>(B x) {
return new Either<A, B>(x);
}
var e1 = Left<string, string>("");
var e2 = Right<string, string>("");
How to disambiguate between the two constructors when the two type parameters are the same?
I'll start by not answering your question, and then finish it up with an actual answer that lets you work around this problem.
You don't have to because you should never get yourself into this position in the first place. It is a design error to create a generic type which can cause member signatures to be unified in this manner. Never write a class like that.
If you go back and read the original C# 2.0 specification you'll see that the original design was to have the compiler detect generic types in which it was in any way possible for this sort of problem to arise, and to make the class declaration illegal. This made it into the published specification, though that was an error; the design team realized that this rule was too strict because of scenarios like:
class C<T>
{
public C(T t) { ... }
public C(Stream s) { ... deserialize from the stream ... }
}
It would be bizarre to say that this class is illegal because you might say C<Stream> and then be unable to disambiguate the constructors. Instead, a rule was added to overload resolution which says that if there's a choice between (Stream) and (T where Stream is substituted for T) then the former wins.
Thus the rule that this kind of unification is illegal was scrapped and it is now allowed. However it is a very, very bad idea to make types that unify in this manner. The CLR handles it poorly in some cases, and it is confusing to the compiler and the developers alike. For example, would you care to guess at the output of this program?
using System;
public interface I1<U> {
void M(U i);
void M(int i);
}
public interface I2<U> {
void M(int i);
void M(U i);
}
public class C3: I1<int>, I2<int> {
void I1<int>.M(int i) {
Console.WriteLine("c3 explicit I1 " + i);
}
void I2<int>.M(int i) {
Console.WriteLine("c3 explicit I2 " + i);
}
public void M(int i) {
Console.WriteLine("c3 class " + i);
}
}
public class Test {
public static void Main() {
C3 c3 = new C3();
I1<int> i1_c3 = c3;
I2<int> i2_c3 = c3;
i1_c3.M(101);
i2_c3.M(102);
}
}
If you compile this with warnings turned on you will see the warning I added explaining why this is a really, really bad idea.
No, really: How to disambiguate between the two constructors when the two type parameters are the same?
Like this:
static Either<A, B> First<A, B>(A a) => new Either<A, B>(a);
static Either<A, B> Second<A, B>(B b) => new Either<A, B>(b);
...
var ess1 = First<string, string>("hello");
var ess2 = Second<string, string>("goodbye");
which is how the class should have been designed in the first place. The author of the Either class should have written
class Either<A, B>
{
private Either(A a) { ... }
private Either(B b) { ... }
public static Either<A, B> First(A a) => new Either<A, B>(a);
public static Either<A, B> Second(B b) => new Either<A, B>(b);
...
}
...
var ess = Either<string, string>.First("hello");
The only way I could think of would be to use reflection to iterate each constructor and then determine which one should be used based on the method body.
Of course this is way over the top and you should really just refactor your class, but it is a working solution.
It requires that you identify the byte[] for the method body that you want to use and 'hard code' that into the program (or read from file etc.). Of course you need to be very cautious that the method body may change over time, for example if the class is modified at any point.
// You need to set (or get from somewhere) this byte[] to match the constructor method body you want to use.
byte[] expectedMethodBody = new byte[] { 0 };
Either<string, string> result = null; // Will hold the result if we get a match, otherwise null.
Type t = typeof(Either<string, string>); // Get the type information.
// Loop each constructor and compare the method body.
// If we find a match, then we invoke the constructor and break the loop.
foreach (var c in t.GetConstructors())
{
var body = c.GetMethodBody();
if (body.GetILAsByteArray().SequenceEqual(expectedMethodBody))
{
result = (Either<string, string>)c.Invoke(new object[] { "123" });
break;
}
}
Disclaimer: Although I have tested this code briefly and it seems to work, I am really sceptical about how reliable it is. I do not know enough about the compiler to be comfortable in saying the method body wont change on a re-compile even if the code isn't changed. It may be that it would become more reliable if this class was defined in a pre-compiled DLL, again I don't know for sure though.
There may be other information you could get via reflection that might make it easier to identify the correct constructor. However, this was the first that came to mind and I haven't really looked into any other possible options at this time.
It would be much simpler if we could rely on the order of the constructors, but as quoted from MSDN, it is not reliable:
The GetConstructors method does not return constructors in a particular order, such as declaration order. Your code must not depend on the order in which constructors are returned, because that order varies.
I have seen numerous posts debating about overloading a method by changing its return type, but, the following program should ideally work fine, because the variable i of type integer can only hold integer values.
So, it should ideally call the function int print(int a) function and not even look at the function float print(int a) because it returns a float value, and in main(), I have used an integer variable to hold the value returned by the method, and an integer variable can never hold a float value ..
The following code demonstrates it →
class temp
{
public float print(int a)
{
int l=12.55;
return l;
}
public int print(int a)
{
int p=5;
return p;
}
}
class Program
{
static void Main(string[] args)
{
temp t=new temp();
int i=t.print(10);
A.Read();
}
}
In other scenario, where I do something like this →
class temp
{
public float print(int a)
{
int l=12.55;
return l;
}
public int print(int a)
{
int p=5;
return p;
}
}
class Program
{
static void Main(string[] args)
{
temp t=new temp();
float f=t.print(10);
A.Read();
}
}
Here, I accept that the compiler should generate an error, because it falls in a dilemma whether to call public int(int a) or public float(int a), and because a variable of type float can holding both integer and float values ..
There is no return-type overloading in c#. What if you had ignored the return value, or assigned it to an Object? Then which overload would be called? There are so many ambiguous scenarios, this would be nearly impossible to implement.
It's not because of that, it's because of other scenarios.
For example, you know when you call Console.ReadLine() just to wait for user input? (e.g. press enter to continue)? Well, you could do the same with your print method in this case. Which one should it call then? Should it call the float method? Should it call the int method? What happens when they use var? dynamic? Generics?
You could argue that it should compile in your case, because you're not using it like that. However, what if it's in a class library? What if it's called through reflection? You can't just spend half of the compile-time checking whether it will be called anywhere else, without the return type.
And also, it wouldn't be good practice. You couldn't easily tell them apart, so you could cause so many bugs with this.
So in short: it's possible, but it's so, so impractical it would never be considered as wanted by language designers[1].
[1]: Interesting sidenote, MSIL allows it. So if you used ildasm, you could get return type overloading. Mainly because to call a function in it, you need to do this: call MyReturnType MyFunc(MyType, MyOtherType)
say you had
int foo(int a){..}
double foo(int a) {...}
and then called
foo(1);
or var x = foo(1);
So which one did you mean to be called?
Trying to cope with the former would mean the compiler would have to figure out how the function was being called in the first case, the second is crossed fingers time.
Aside from that being PIA for the language designer what about the programmer? Seeing as it's easily corrected with fooInt, and FooFloat, why would anyone choose the extra level of complexity (not to mention performance with late binding) in favour of a more meaningful name?
The whole point of a strong and statically typed language is to remove this sort of ambiguity at compile time.
I´m working with C# + Unity (2.1). Intercepting methods works fine if a call comes from outside, but between methods inside the same class only the first method is intercepted.
For example:
[InterceptorAttribute]
public int A(int a, int b)
{
return B(a, b);
}
[InterceptorAttribute]
public int B(int a, int b)
{
return a+b;
}
The call to method B() is not intercepted.
Can anyone help?
If you look at how interception is implemented, it becomes clear as to why this happens. An interceptor is basically a proxy that wraps around the original object and forwards calls to it, in addition to calling any associated handlers:
public int A(int a, int b)
{
callHandlers();
return originalObject.A(a, b);
}
public int B(int a, int b)
{
callHandlers();
return originalObject.B(a, b);
}
Even though the two calls are individually intercepted, once originalMethod.A is invoked, the call to B will only invoke originalObject.B, not proxy.B.
Perhaps if you explain what you're using interception for, there may be a better solution to what you're trying to do.
I was thinking of List's functionality and not thinking about the fact that Count() was an extension method when I made the false assumption that I could write a class having a same named property and method. The motivation in my mind at the time was I could "parameterize a property" for special cases.
I realize now that I can do it, provided I utilize an extension method.
Is this intentionally disallowed in classes but allowed in extensions or simply a non-existant feature?
void Main()
{
var list = new List<string>();
// You compile code that gets the property named Count
// and calls the method named Count()
list.Add("x");
Console.WriteLine (list.Count);
list.Add("x");
Console.WriteLine (list.Count());
var c = new C();
Console.WriteLine (c.Count);
Console.WriteLine (c.Count());
}
public class C
{
public int Count { get { return 3; } }
// But you cannot compile a class that contains both a property
// named Count and a method named Count()
//public int Count () { return 0; } // <-- does not compile
}
public static class X
{
public static int Count(this C c)
{
return 4;
}
}
I remember asking this question like 10 years ago on one of Microsoft groups:
http://www.developmentnow.com/g/36_2003_9_0_0_195928/methods-and-properties-of-the-same-name.htm
and as you can see there was no convincing answer.
This is of course easily possible in CIL, as properties translate to paris of getXX/setXX methods.
This is because Count(this C c) is an extension method and doesn't actually make a part of the type.
That means that you can have a method Count() in C + extension Count(). If you call it, will be called instance method.
So if we think about a property there is even less problems with that.
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.