The following is an interview question. I came up with a solution, but I'm not sure why it works.
Question:
Without modifying the Sparta class, write some code that makes MakeItReturnFalse return false.
public class Sparta : Place
{
public bool MakeItReturnFalse()
{
return this is Sparta;
}
}
My solution: (SPOILER)
public class Place
{
public interface Sparta { }
}
But why does Sparta in MakeItReturnFalse() refer to {namespace}.Place.Sparta instead of {namespace}.Sparta?
But why does Sparta in MakeItReturnFalse() refer to {namespace}.Place.Sparta instead of {namespace}.Sparta?
Basically, because that's what the name lookup rules say. In the C# 5 specification, the relevant naming rules are in section 3.8 ("Namespace and type names").
The first couple of bullets - truncated and annotated - read:
If the namespace-or-type-name is of the form I or of the form I<A1, ..., AK> [so K = 0 in our case]:
If K is zero and the namespace-or-type-name appears within a generic method declaration [nope, no generic methods]
Otherwise, if the namespace-or-type-name appears within a type declaration, then for each instance type T (§10.3.1), starting with the instance type of that type declaration and continuing with the instance type of each enclosing class or struct declaration (if any):
If K is zero and the declaration of T includes a type parameter with name I, then the namespace-or-type-name refers to that type parameter. [Nope]
Otherwise, if the namespace-or-type-name appears within the body of the type declaration, and T or any of its base types contain a nested accessible type having name I and K type parameters, then the namespace-or-type-name refers to that type constructed with the given type arguments. [Bingo!]
If the previous steps were unsuccessful then, for each namespace N, starting with the namespace in which the namespace-or-type-name occurs, continuing with each enclosing namespace (if any), and ending with the global namespace, the following steps are evaluated until an entity is located:
If K is zero and I is the name of a namespace in N, then... [Yes, that would succeed]
So that final bullet point is what picks up the Sparta class if the first bullet doesn't find anything... but when the base class Place defines an interface Sparta, it gets found before we consider the Sparta class.
Note that if you make the nested type Place.Sparta a class rather than an interface, it still compiles and returns false - but the compiler issues a warning because it knows that an instance of Sparta will never be an instance of the class Place.Sparta. Likewise if you keep Place.Sparta an interface but make the Sparta class sealed, you'll get a warning because no Sparta instance could ever implement the interface.
When resolving a name to its value the "closeness" of the definition is used to resolve ambiguities. Whatever definition is "closest" is the one that is chosen.
The interface Sparta is defined within a base class. The class Sparta is defined in the containing namespace. Things defined within a base class are "closer" than things defined in the same namespace.
Beautiful question! I'd like to add a slightly longer explanation for those who don't do C# on a daily basis... because the question is a good reminder of name resolution issues in general.
Take the original code, slightly modified in the following ways:
Let's print out the type names instead of comparing them as in the original expression (i.e. return this is Sparta).
Let's define the interface Athena in the Place superclass to illustrate interface name resolution.
Let's also print out the type name of this as it is bound in the Sparta class, just to make everything very clear.
The code looks like this:
public class Place {
public interface Athena { }
}
public class Sparta : Place
{
public void printTypeOfThis()
{
Console.WriteLine (this.GetType().Name);
}
public void printTypeOfSparta()
{
Console.WriteLine (typeof(Sparta));
}
public void printTypeOfAthena()
{
Console.WriteLine (typeof(Athena));
}
}
We now create a Sparta object and call the three methods.
public static void Main(string[] args)
{
Sparta s = new Sparta();
s.printTypeOfThis();
s.printTypeOfSparta();
s.printTypeOfAthena();
}
}
The output we get is:
Sparta
Athena
Place+Athena
However, if we modify the Place class and define the interface Sparta:
public class Place {
public interface Athena { }
public interface Sparta { }
}
then it is this Sparta -- the interface -- that will be available first to the name lookup mechanism and the output of our code will change to:
Sparta
Place+Sparta
Place+Athena
So we have effectively messed up with the type comparison in the MakeItReturnFalse function definition just by defining the Sparta interface in the superclass, which is found first by the name resolution.
But why does C# chose to prioritize interfaces defined in the superclass in the name resolution? #JonSkeet knows! And if you read his answer you'll get the details of the name resolution protocol in C#.
Related
There is an exercise "OverloadResolutionOverride"
What will be the output of the following code:
class Foo
{
public virtual void Quux(int a)
{
Console.WriteLine("Foo.Quux(int)");
}
}
class Bar : Foo
{
public override void Quux(int a)
{
Console.WriteLine("Bar.Quux(int)");
}
public void Quux(object a)
{
Console.WriteLine("Bar.Quux(object)");
}
}
class Baz : Bar
{
public override void Quux(int a)
{
Console.WriteLine("Baz.Quux(int)");
}
public void Quux<T>(params T[] a)
{
Console.WriteLine("Baz.Quux(params T[])");
}
}
void Main()
{
new Bar().Quux(42);
new Baz().Quux(42);
}
There answer is:
Bar.Quux(object)
Baz.Quux(params T[])
There is an explanation on the site:
If compiler found a suitable signature for a method
call in the “current” class, compiler will not look to parents
classes.
Is it considered that the overloaded Quux(int) method is in the base class, and not in the current one? If so, how i can call exactly Quux(int) method in current class?
This is definitely an interesting effect of what happens when the compiler does its method resolution.
Let's go to the specification and see what we can get out of that (This is my understanding and I am by no means an expert in reading the specification, so if I got something wrong, please let me know!).
The first step is to find methods that have parameters that are Applicable with the first bullet reading:
Each argument in A [Where A is the argument list] corresponds to a parameter in the function member
declaration as described in Corresponding parameters, and any
parameter to which no argument corresponds is an optional parameter.
So now we go check out what a Corresponding parameter is and we get:
For virtual methods and indexers defined in classes, the parameter
list is picked from the most specific declaration or override of the
function member, starting with the static type of the receiver, and
searching through its base classes.
And we also have
For all other function members and delegates there is only a single
parameter list, which is the one used.
Therefore, for the class Bar, we find two methods the fit the bill:
Bar.Quux(object). This is from the second paragraph because it is defined on the type directly.
Foo.Quux(int). This is from the derived type by following the override up to the virtual method declaration.
For the Baz class we get 3:
Baz.Quux(int[]). This is defined on the type.
Bar.Quux(object). This is defined in a parent class and is visible to the scope of Baz.
Foo.Quux(int). This is the virtual declaration of the override.
This gives us 2 method matches in Bar, and 3 possible method matches in Baz. This means we need to do further culling of the parameter set with the following next set (Emphasis mine):
The set of candidate methods is reduced to contain only methods from
the most derived types: For each method C.F in the set, where C is the
type in which the method F is declared, all methods declared in a base
type of C are removed from the set. Furthermore, if C is a class type
other than object, all methods declared in an interface type are
removed from the set. (This latter rule only has affect when the
method group was the result of a member lookup on a type parameter
having an effective base class other than object and a non-empty
effective interface set.)
Therefore, for Bar, we will cull Foo.Quux(int) because it is declared in a base type and is therefore removed from the set.
For Baz, we remove the following two methods because they are both declared in base types:
Bar.Quux(object)
Foo.Quux(int)
Now, each set has only one method, and we can execute the two methods Bar.Quux(object) and Baz.Quux<int>(int[]).
Picking the right Method
So this begs the question, can we force the correct method to be called? And based on the second resolution step, where it uses the most derived type, the answer is that yes we can.
If we want to call Foo's methods, we need to set the type of our caller to Foo. If we want Baz to call Bar's method, then we will need to set Baz to Bar.
Considering the following set of method calls:
new Bar().Quux(42);
new Baz().Quux(42);
((Foo)new Bar()).Quux(42);
((Foo)new Baz()).Quux(42);
((Bar)new Baz()).Quux(42);
We get the following output:
Bar.Quux(object)
Baz.Quux(params T[])
Bar.Quux(int)
Baz.Quux(int)
Bar.Quux(object)
And are able to target the specific methods that we want to using a similar method resolution as above.
One More Step
If we change the definition of Baz to be following:
class Baz : Bar
{
public override void Quux(int a)
{
Console.WriteLine("Baz.Quux(int)");
}
}
And then make the method call: new Baz().Quux(42); our output is still: Bar.Quux(object). This seems strange because of the fact that we have a method override defined within Baz directly. However, the originating type for the method is Foo which is less specific than Bar. So when we match our parameter lists, we end up with Bar.Quux(object) and Foo.Quux(int) since the int parameter list is defined on Foo. Therefore, Foo.Quux(int) is culled in the second step since Bar is more derived than Foo, and we call Bar.Quux(object).
I think the moral of the story here is don't name methods the same as overrides!
As other note, the way to call the method you wan't is to downcast: (Bar)(new Baz).Quux(42);.
But why does the compiler choose the generic method? Isn't an exact non generic match preferred over a generic method when resolving method resolution?
Yes, but another rule applies here too; method resolution will prefer the nearest applicable method, nearest meaning where the method is declared in relation to the callsite.
Uhm... Quux(int) is declared in Baz so I'm not really sure...
No! Overriden methods belong to the class that implements the virtual method; in this case, as far as the compiler is concerned, the "owner" of Quux is Foo, not Baz.
And why would the compiler apply such a rule? Well, suppose the following scenario:
Company Alpha publishes a class A:
class A { ... }
And company Beta goes ahead and consumes A by extending it with B:
class B: A {
public void Frob<T>(T frobbinglevel) { ... }
... }
Everything is honky dory and Beta is having tremendous success with its brilliant frobbing. Company Alpha decides to have a go with its own frobbing and publishes a new version of A:
class A {
public virtual void Frob(int frobbinglevel) { ... }
... }
Beta recompiles its library with Alpha's updates and now what should happen? Should the compiler start choosing A.Frob(1) over B.Frob(1), A.Frob is a non generic exact match?
But hey... Beta hasn't changed anything and now its class is not working as it should! Suddenly, without any change in its code, method resolution is choosing different methods, breaking its customers...that doesn't seem right. This is the reason why the rule exists.
To call exactly Quux(int) from Bar or Baz you should cast Bar or Baz to Foo:
Foo bar = new Bar();
Foo baz = new Baz();
bar.Quux(42);
baz.Quux(42);
The output:
Bar.Quux(int)
Baz.Quux(int)
When I run code analysis (VS2013) with the 'Microsoft Managed Recommend Rules' rule set, the only warnings I get for my class library are of type CA1033: 'Interface methods should be callable by child types'. But I don't understand the rule in this situation:
/// An object that has a chemical formula
public interface IChemicalFormula
{
/// The chemical formula of the object
ChemicalFormula ChemicalFormula {get;}
}
public class ChemicalFormula: IChemicalFormula
{
ChemicalFormula IChemicalFormula.ChemicalFormula
{
get { return this; }
}
}
The docs recommends making a protected method with the same name so that deriving types can access it, but you cannot name a method the same as the enclosing type. They also recommend making the class sealed, but I don't want it to be sealed in this case. Is this a time just to ignore this rule, or is there an appropriate way to handle it?
EDIT
To add clarification why the class/interface is designed this way, I have another class, Peptide that contains a IChemicalFormula[] array to store modifications. Not every modification necessarily derives directly from ChemicalFormula, but they need to implement the IChemicalFormula interface. Therefore, if I modify an instance of a peptide withsome molecule (H2O for example), then ChemicalFormula class needs to also implement IChemicalFormula.
This is the description of the rule:
Consider a base type that explicitly implements a public interface
method. A type that derives from the base type can access the
inherited interface method only through a reference to the current
instance (this in C#) that is cast to the interface. If the derived
type re-implements (explicitly) the inherited interface method, the
base implementation can no longer be accessed. The call through the
current instance reference will invoke the derived implementation;
this causes recursion and an eventual stack overflow.
I think you should consider evaluating the usage of this property. A good example where TDD could be used to figure out the interface. There are some possible usages (and some invalid ones) below. I am not yet sure what you intend to achieve by looking at those.
In your example, let's say another class, NewChemicalForumla is derived from ChemicalForumula, and references ChemicalFormula, what does that mean?
public class NewChemicalFormula: ChemicalFormula
{
public void Method()
{
Console.WriteLine("{0}", ChemicalFormula.GetType()); // Compile error
Console.WriteLine("{0}", this.ChemicalFormula.GetType()); // Effectively same as above, compile error
Console.WriteLine("{0}", ((IChemicalFormula)this).ChemicalFormula.GetType()); // Works, is that what you intend?
}
}
Now from outside the class, there are two possibilities:
When you have a handle to a derived class:
new NewChemicalFormula().ChemicalFormula.GetType() // Error
or
// This works, is that what you intend to achieve?
((IChemicalFormula)new NewChemicalFormula()).ChemicalFormula.GetType()
When you have a handle to the IChemicalFormula already. In this case, ChemicalFormula seems redundant:
IChemicalFormula formula = new NewChemicalFormula();
Console.WriteLine("{0}", formula.GetType()); // Works, returns NewChemicalFormula
Console.WriteLine("{0}", formula.ChemicalFormula.GetType()); // Works, returns NewChemicalFormula
Console.WriteLine("{0}", formula.ChemicalFormula.Method()); // Compile error
formula.ChemicalFormula.Method() leads to an error because you must cast it to NewChemicalFormula before you can use Method(). Just because the property returns this doesn't help solve this problem.
So the FXCop warning is worth considering, and evaluating the design.
This question already has answers here:
Why are C# 4 optional parameters defined on interface not enforced on implementing class?
(7 answers)
Closed 9 years ago.
In an abstract class
public abstract class base
{
abstract public int Func(bool flag = true);
}
I made a change in the derived version:
public class derived : base
{
public override int Func(bool flag = false){}
}
Debugging shows the compiler uses true as default. I expected otherwise, why does it behave thus?
This behavior is stated in the C# language specification at §7.5.1.1 (Corresponding Parameters, emphasis mine):
For each argument in an argument list there has to be a corresponding
parameter in the function member or delegate being invoked. The
parameter list used in the following is determined as follows:
For virtual methods and indexers defined in classes, the parameter list is
picked from the most specific declaration or override of the function
member, starting with the static type of the receiver, and searching
through its base classes
During binding (the process of associating the method to call to an invocation) the compiler finds a list of arguments using the rules stated above then a set of candidate methods conforming to that argument list. Among these the best one is picked and bound to the invocation.
Take this code:
BaseClass b = new DerivedClass( );
b.Func( );
During binding the argument list used is the one declared in BaseClass.Func (because that is the static type of b) and the set of candidate methods is BaseClass.Func and DerivedClass.Func (they are said to be applicable, because both argument list correspond to the one chosen). Then DerivedClass.Func is decided to be the best candidate, as expected, and therefore bound to the call using the parameter list of BaseClass.Func, thus using flag = true.
You can find more details in §7.5.3 (Overload resolution). Finally, in case you wonder, abstract methods are considered virtual, as noted in §10.6.6 (Abstract methods):
An abstract method declaration introduces a new virtual method but does not provide
an implementation of that method.
I've created a sample that mimics your situation. Long story short: which default value is used depends on whether you access the instance by a variable of the type of the base class or the derived class. So the compiler detects the default value of the optional parameter based on the type of variable. This makes sense as you could store any instance of a derived class in the variable (polymorphism). It might not even be clear at compile time, which the type if instance is (e.g. if you configure your system to use a specific type). All the compiler knows is the type of the variable and that any instance that you put into it in a type-safe manner offers the same interface.
using System;
public abstract class MyBase
{
public abstract bool GetValue(bool value = true);
}
public class MyDerived : MyBase
{
public override bool GetValue(bool value = false)
{
return value;
}
}
public class Test
{
public static void Main()
{
var derived = new MyDerived();
Console.WriteLine("Value = {0}", derived.GetValue());
MyBase myBase = derived;
Console.WriteLine("Value = {0}", myBase.GetValue());
}
}
I assume that you call the method on a variable of the type of the base class which would explain the behavior.
Basically, this resembles the behavior if you don't override the method but shadow it. It is a situation you will want to avoid in almost all circumstances because the risk that the code will not behave in the way you expect it is relatively high. Therefore I'd suggest to get rid of the optional parameters and make them required ones (and maybe create an overload without the parameter). Having to type less and being able to change the default value later is not worth the risk of having a unexpected behavior of your code. The behavior might be transparent to you now, but I doubt that it will be some months later or to coworkers of yours that have to maintain the code.
I am not sure why the enum there must be public in order to be used with the delegate. I assumed when on namespace level, the whole app can access it, as it is in the scope.
namespace Test
{
enum Days
{
Monday,Tuesday
}
class TestingClass
{
public delegate void DelTest(Days d) /// ERROR, type enum is less accessible
}
}
Your delegate type is actually declared within an internal class, so it's effectively internal too (in some senses, anyway). That's why your example as shown will compile (after adding the semi-colon). To make it break, you'd have to make TestingClass public too. So options:
Leave it as shown
Make the delegate explicitly internal, if you want TestingClass to be public
Make the enum explicitly public, if you want everything to be public
Just to explain why your current code would be broken if TestClass were public: the delegate would be public, and therefore visible outside the current assembly. That means all its parameters and the return type have to be visible too.
Don't forget that the default access level for a member in C# is always "the most restrictive access level that could be explicitly specified for that member" - so for a top-level type (including an enum), the default accessibility is internal.
The accessibility of your enum must match the delegate. Think about how you're going to call it.
new TestingClass.DelTest(Days.Monday).Invoke();
To be able to do this from a different assembly, the Days enum must be public. If you don't want it to be public, change the accessibility of the delegate to match that of the enum, e.g. set both to be internal.
I assumed when on namespace level, the whole app can access it
No, the whole assembly can access it. The default access level is internal.
Edit: When I change your code to use a public class:
enum Days { ... }
public class TestingClass { void M(Days d) {} }
I do get a compile error
Inconsistent accessibility: parameter type 'Test
.Days' is less accessible than ...
And that is what #firefox explains: a parameter-type in a public method must also be public, to avoid inconsistencies. Currently your Days type is less accessible (internal).
This piece of code compiles fine for me too, with the addition of the semi colon.
The error of "parameter type is less accessible than the delegate" would only occur if the class accessibility is raised, as currently they are defined with the same accessibility level, internal.
e.g.
namespace Test
{
enum Days
{
Monday, Tuesday
}
public class TestingClass
{
public delegate void DelTest(Days d); // This will produce an error...
}
}
I think I finally get the point of constraints, but still a bit confused. Can someone tell me if the following is right?
Basically, if you inherit a class you may want to make sure that the class you inherit also inherits from some other class or some other interface.
It's confusing because presumably you would know that you would only want to inherit from a class that had the things you wanted but I guess with generics you can get a compile error at one point and not know that the problem actually stems from the fact that some class is not inherited somewhere else and you can get errors that make sense if you add constraints in the right areas.
Does that make sense? Am I on the right track?
I don't think that's the point of constraints, (but I may be wrong).
As I understand it, constraints don't have much to do with inheritance, per se. What you're really doing is putting constraints on the type that may be used if you are using (instantiating) a class that has type arguments.
Classes with type arguments are like Mad-Libs, and constraints are like the instructions that appear under the blanks:
"Bob like to ______ with his friends every night." (that's a madlib)
"Bob likes to _(verb)___ with his friends every night" (a madlib with instructions).
Check this:
//class with type arguments
public class MadLib<W> {
public void addWord(W word) {
System.Console.WriteLine("bob likes to " + word + " with his friends");
}
}
//class with type arguments and contraints (note i'm not inheriting nothin)
public class MadLib<W> where W:Verb{
public void addWord(W word) {
System.Console.WriteLine("bob likes to " + word + " with his friends");
}
}
Not exactly. Constraints are used to specify what behaviors and/or types a generic parameter can exhibit.
For example, if you declare a class:
class GenericDisposableHandler<T>
{
public void DoOperationOnT(T someVariable)
{
// can't really do much with T since its just an object type
}
}
and know for a fact that the generic parameter T should always be something that implements IDisposable, you would do:
class GenericDisposableHandler<T> where T : IDiposable
{
public void DoOperationOnT(T someVariable)
{
// Now you can treat T as IDisposable
someVariable.Dispose();
}
}
There are many other constraint types you can use.
Not really. Constraints are only applicable when you are defining a Generic class templare, (not when you inherit from a class).
When you define a generic, you are saying that this is a "template" or pattern, for some as yet undefined/unknown class with an as yet unknown Type, T, that will be created somewhere else based on this pattern and with an explicitly provided Type T. The constraint limits WHICH Types T can be used in the other place where you actually create the real type from the template/pattern
as in
//Define the generic here, with arbitrary type T
public class MyClass<T> where T: SomeOtherClass
{
// template/pattern methods, proerpties, fields, etc.
}
Create actual class here with explicitly provided Type "DerivedClass"
public MyClass<DerivedClass> myC = new MyClass<DerivedClass> ();
which will succeed if and only if DerivedClass inherits from SomeOtherClass
You can only inherit from one class, however you can implement several interfaces. The inheritance means that your class gets (inherits) whatever properties and methods that the base class specifies. As long as they're not marked as private, the inheriting class can call those methods as it's own.