Multiple inheritance problem in C# - c#

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.

Related

C# optional parameters: Why can I define the default different on interface and derived class?

With C#, we now can have optional parameters, and give them default values like this:
public abstract class ImporterBase : IImporter {
public void ImportX(bool skipId = true) {
//....
}
}
Now, suppose in the interface we derive from, we have
public interface IImporter {
void ImportX(bool skipId = false);
}
See, that the default value is defined as different in the base class as in the interface. This is really confusing, as now the default value depends whether I do
IImporter interfaceImporter = new myConcreteImporter(); //which derives from ImporterBase
interfaceImporter.DoX(); //skipId = false
or
ImporterBase concreteImporter = new myConcreteImporter(); //which derives from ImporterBase
concreteImporter.DoX(); //skipId = true
Why is it allowed to define the default value differently in both the interface and the derived class?
Note: this question similar, but focuses on the optionality, not on the value.
To clarify, I'm interpreting the question to be:
If a method is defined in an interface / base class which has a method which has a parameter with a default value, and a class implements / overrides that method but provides a different default value, why doesn't the compiler warn?
Note that this doesn't cover the case where the implementation doesn't provide any default value -- that case is explained by Eric Lippert.
I asked this on the csharplang gitter channel, and the response from someone who has been heavily involved in the language design for a long time was:
i think an analyzer sounds very good for this.
From that, and the other links posted here (which don't even mention this specific case), my best guess is that this specific case just wasn't considered, or was briefly considered but dismissed as too niche. Of course, once C# 4 was released, there was no way to add a compiler error or warning without breaking backwards compatibility.
You could write an analyzer which catches this case (which had a code fix to correct the default value), and try to get it incorporated into Roslyn.
As a footnote, there are a few cases I can see which would cause issues.
An interface changes the default value for one of its parameters
This is already a binary-breaking change, and this would promote it to a source-breaking change.
Two interfaces with different default values
interface I1
{
void Foo(bool x = false);
}
interface I2
{
void Foo(bool x = true);
}
class C : I1, I2
{
...?
}
If you did want to specify a default value for C.Foo, this case could be solved by explicitly implementing one of the interfaces:
class C : I1, I2
{
public void Foo(bool x = false) { ... }
void I2.Foo(bool x) => Foo(x);
}
Alternatively you could just ignore this case, and not warn.
Adding an interface in a child class
interface I1
{
void Foo(bool x = false);
}
class Parent
{
public void Foo(bool x = true) { ... }
}
class Child : Parent, I1
{
...?
}
I'm not sure what an intuitive solution to this would be, but since it's so niche I'd be tempted just to ignore it, and not warn.
There's a good reason for it. See here.
The short answer is though, if it treated the optional values as part of the method signature, it cause some problems. Imagine the code below:
public abstract class A
{
public abstract void SomeFunction(bool flag);
}
public class B : A
{
public override void SomeFunction(bool flag = true)
{
//do something
Console.WriteLine(flag);
}
}
If the optional parameter value was part of the method signature then I'd get a compilation error since A doesn't have bool flag = true in the method signature. It's an easy fix for sure but if you shipped A to a third party and their custom code created class B, they'd have to go change your code to have the optional parameter. Also keep in mind this is exacerbated when there are several levels of inheritance. So the easiest fix was to not consider the optional parameter value as part of the method signature for these purposes.

Disambiguate between two constructors, when two type parameters are the same

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.

Call any class sharing the same method name in C#

I have a significant number of classes which share the same method name, but don not share a common base/interface. I cannot touch these classes, however, can I call the method irrespective of the defining class?
Eg:
Namespace n1: class A { void M1(n1.CustObj ob1){} }
Namespace n2: class B { void M1(n2.CustObj ob1){} }
Would it be possible to abstract from these common methods/parameters, like so?
method(Object obj)
{
obj.M1(new CustObj() {
x = 3;
}); // CustObj can either belong to n1 or n2
}
You have a number of classes, each of which has a method, with the same name, but with a different signature. The identical method names are a red herring here therefore as they are different methods.
This therefore rules out using dynamic or reflection to provide a single method that can handle all of them, unless you then hard-code tests for each type within the one method, or take Jonathan Wood's approach of passing in an existing instance of CustObj via a dynamic parameter too.
One solution might be to create extension methods for each type:
public void Method(this A obj)
{
obj.M1(new n1.CustObj()
{
x = 3
});
}
public void Method(this B obj)
{
obj.M1(new n2.CustObj()
{
x = 3
});
}
and so on. Then at least you can do someObj.Method(); on A, B and so forth.
You could use either the dynamic keyword or reflection.
Of the two, I prefer dynamic. However, since your constructor argument is also a different type you'd need to do something like this:
void method(dynamic obj, dynamic arg)
{
arg.x = 3;
obj.M1(arg);
}
I understand it's unlikely that your code is set up to do this but you haven't shown much of how your method is used. And in the end, this might be the best you can do if you're unable to modify the existing classes.

Generic class with overridden method - which gets called?

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.

Field initializer accessing `this`: invalid in C#, valid in Java? [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 9 years ago.
Improve this question
First, an introduction:
This code:
class C
{
int i = 5;
byte[] s = new byte[i];
}
fails to compile with the following error:
A field initializer cannot reference the nonstatic field, method, or property `C.i'
Resharper says something similar: Cannot access non-static field i in static context.
This is inline with what the C# spec says -- that a field initializer can't access the instance currently being created (this) or, by extension, any of the instance fields:
A variable initializer for an instance field cannot reference the
instance being created. Thus, it is a compile-time error to reference
this in a variable initializer, as it is a compile-time error for a
variable initializer to reference any instance member through a
simple-name.
However, this works just fine in Java:
class C {
int i = 5;
byte s[] = new byte[i]; //no errors here
}
Still with me? Ok, here's the question. Err, questions.
In a hypothetical world where this would be valid in C#, I'm wondering: would it even be possible? If so, what would be the pros and cons that it would add to the table?
Also, since it's really supported by Java, do the same pros/cons hold for Java? Or is there a fundamental difference in the way type initializers work in the two languages?
In short, the ability to access the receiver before the constructor body runs is a feature of marginal benefits that makes it easier to write buggy programs. The C# language designers therefore disabled it entirely. If you need to use the receiver then put that logic in the constructor body.
as for why the feature is legal in Java, you'll have to ask a Java designer.
In C#, field initializers are merely convenience semantics for the developer. The compiler moves all field initializers into the body of the constructor ABOVE where the call is made to the base constructor. So fields are initialized going up the ancestor chain, and the class is initialized from the base down.
Static references are ok because they are initialized before anything else.
By no means is this an authoritative answer, but let me make an educated guess.
There is a fundamental difference, and I think the answers to the other questions are related to this difference.
It lies in order-of-type-initialization, especially in the context of inheritance.
So, how does instance initialization work?
In C#:
all instance field initializers run first, "up" the inheritance chain, from most derived to base class.
then the ctors run, "down" the chain, from base to derived.
The possibility of ctors calling each-other or (explicitely) calling ctors of base classes doesn't change the situation, so I'll leave it out.
What basically happens is, this runs for each chass in the chain, starting with the most derived:
Derived.initialize(){
derivedInstance.field1 = field1Initializer();
[...]
Base.Initialize();
Derived.Ctor();
}
A simple example shows this:
void Main()
{
new C();
}
class C: B {
public int c = GetInt("C.c");
public C(){
WriteLine("C.ctor");
}
}
class B {
public int b = GetInt("B.b");
public static int GetInt(string _var){
WriteLine(_var);
return 6;
}
public B(){
WriteLine("B.ctor");
}
public static void WriteLine(string s){
Console.WriteLine(s);
}
}
Output:
C.c
B.b
B.ctor
C.ctor
That means that if accessing fields in a field initializer was valid, I could do this disaster:
class C: B {
int c = b; //b is a field inherited from the base class, and NOT YET INITIALIZED!
[...]
}
In Java:
Long, interesting article about type initialization here. To summarize:
It's a bit more complicated, because besides the notion of instance field initializers, there's the notion of an (optional) instance initializer, but here's the gist of it:
Everything runs down the inheritance chain.
the instance initializer of the base class runs
the field initializers of the base class run
the ctor(s) of the base class run
repeat above steps for the next class down the inheritance chain.
repeat previous step until reaching the most derived class.
Here's the proof: (or run it yourself online)
class Main
{
public static void main (String[] args) throws java.lang.Exception
{
new C();
}
}
class C extends B {
{
WriteLine("init C");
}
int c = GetInt("C.c");
public C(){
WriteLine("C.ctor");
}
}
class B {
{
WriteLine("init B");
}
int b = GetInt("B.b");
public static int GetInt(String _var){
WriteLine(_var);
return 6;
}
public B(){
WriteLine("B.ctor");
}
public static void WriteLine(String s){
System.out.println(s);
}
}
Output:
init B
B.b
B.ctor
init C
C.c
C.ctor
What this means is, by the time a field initializer runs, all inherited fields are already initialized (by initializer OR ctor in base class), so it's safe enough to allow this behaviour:
class C: B {
int c = b; //b is inherited from the base class, and it's already initialized!
[...]
}
In Java, like in C#, the field initializers are run in the order of declaration.
The Java compiler even goes through the effort of checking that the field initializers aren't called out-of-order* :
class C {
int a = b; //compiler error: illegal forward reference
int b = 5;
}
* As an aside, you can access fields out-of-order if the initializer calls an instance method to do so:
class C {
public int a = useB(); //after initializer completes, a == 0
int b = 5;
int useB(){
return b; //use b regardless if it was initialized or not.
}
}
It is because field initialisers are moved into the constructor by the compiler (unless static) and so you would need be explicit in your constructor like this:
class C
{
int i = 5;
byte[] s;
public C()
{
s = new byte[i];
}
}
This is a bit of a non-answer, but I like to think of anything in the body of a class as being sequence-independent. It's not supposed to be sequential code that needs to be evaluated in a particular manner--it's just default state for the class. If you use code like that, you're expecting i to be evaluated before s.
Anyways, you can just make i a const (as it should be), anyways.

Categories

Resources