Today I updated to Xamarin.iOS 8.6.0.51. Now I get the following warning:
Warning CS0114: AnApp.AppDelegate.Self' hides inherited member
MonoTouch.Foundation.NSObject.Self'. To make the current member
override that implementation, add the override keyword. Otherwise add
the new keyword (CS0114)
In my AppDelegate.cs I have defined the following property/field:
public static AppDelegate Self { get; private set; }
Than I set it in this way to get a reference to the app delegate (like proposed in this thread):
AppDelegate.Self = this;
This worked before the update. I use this to instantiate some view controllers from the storyboard and some other things (network activity indicator, ...). What do I have to change to get this working? Don't I need this anymore or should I rename Self?
It means the base class of AppDelegate have the member named Self too, compiler warns you that you may be unknowingly hiding the base class member.
If you know what you're doing then you can safely suppress the warning using new keyword.
public static new AppDelegate Self { get; private set; }
That makes absolutely no difference whatsoever, without the new keyword also your App will work the same. It just tells the c# compiler that I'm intentionally using the same name for the member and I'm interested in hiding the base class member.
Related
Let's say I have a Manager class
public class Manager {
public Item Create() {
...
return new Item(...);
}
}
and I have an Item class:
public class Item {
[AllowCallBy(typeof(Manager))]
public Item(...) {
}
...
}
Now, I would like to use the easiest and most straightforward way to analyze the attributes like AllowCallBy at compile time and display errors or warnings. If, in this particular case, a class other than Manager class tries to instantiate Item with new Item(...) I would like to display something like "don't instantiate Item class directly, call Manager.Create(...) instead".
I suppose that at least one of the systems: Roslyn, ReSharper, PostSharp or maybe something else would allow me to do it or something that is very close to what I'm trying to achieve. Could somebody give an example of what to use and how to use it?
This is definitely a code smell as #Habib mentions (can someone link to a specific one?), but without a more complete example it's difficult to offer alternatives beyond what has already been suggested in comments. I'd encourage you to expand your sample or rethink your design.
However, I can present one option that I've used in the past though not for this purpose. You could mark Item's constructor as Obsolete:
public class Item {
[Obsolete("Don't instantiate Item class directly, call Manager.Create(...) instead")]
public Item(...) {
}
...
}
Then in your Manager class, you'd specifically ignore this warning where you invoke the constructor:
public class Manager {
public Item Create() {
...
#pragma warning disable 618
return new Item(...);
#pragma warning restore 618
}
}
This way, whenever someone tries to create their own Item elsewhere in the code, they'll get a level 2 CS0618 warning indicating that they should not use the method (note that I didn't say cannot) with exactly the text entered in the attribute. If warnings as errors is enabled (for all warnings or just this one), then it will be a compile error as you originally wanted.
Be aware, nothing prevents others from adding these pragma statements to get around the error. However, with this method the developer can't say they didn't know they weren't supposed to use the constructor.
Well color me surprised. PostSharp lets you do exactly what you're looking for. In a nutshell, you'd use the ComponentInternalAttribute to control visibility of a type:
public class Item {
[ComponentInternal(typeof(Manager))]
public Item(...) {
}
...
}
According to their documentation linked above, attempting to invoke Item's constructor outside of Manager will yield a compile-time warning:
Method Item.ctor cannot be referenced from [some other method] because of the [ComponentInternal] constraint.
You can make it an error by changing the severity level of the attribute:
public class Item {
[ComponentInternal(typeof(Manager), Severity = SeverityType.Error)]
public Item(...) {
}
...
}
There are way better ways to achieve your goal than your current approach, given that you can actually change that code.
You could for example mark the contructor of Item class as private and add a static factory method to Item class which would be responsible for creating an instance of the class.
Another way is to move Item class to another assembly, mark its constructor as internal and implement another class (a factory) which would be responsible for creating different Item objects. Then you class is visible from other assemblies, but it cannot be directly instantiated, so forces the code user to use provided factory.
Say I have an abstract parent class called "Parent" that implements a method called "DisplayTitle". I want this method to be the same for each subclass that inherits "Parent" - I would like a compile error if a subclass attempts to implement their own "DisplayTitle" method. How can I accomplish this in C#. I believe in Java, I'd just mark the method as "final", but I can't seem to find an alternative in C#. I've been messing around with "sealed" and "override", but I can't get the behavior that I'm looking for.
For example, in this code:
using System;
namespace ConsoleApplication1
{
class Parent
{
public void DisplayTitle() { Console.WriteLine("Parent's Title"); }
}
class ChildSubclass : Parent
{
public void DisplayTitle() { Console.WriteLine("Child's Own Implementation of Title");
}
static void Main(string[] args)
{
ChildSubclass myChild = new ChildSubclass();
myChild.DisplayTitle();
Console.ReadLine();
}
}
}
I'd like to receive a compile error saying that the "ChildSubClass" can't override "DisplayTitle". I currently get a warning - but it seems like this is something that I should be able to do and I don't know the proper attributes to label the method.
How can I accomplish this in C#. I believe in Java, I'd just mark the method as "final", but I can't seem to find an alternative in C#.
The rough equivalent is sealed in C#, but you normally only need it for virtual methods - and your DisplayTitle method isn't virtual.
It's important to note that ChildSubclass isn't overriding DisplayTitle - it's hiding it. Any code which only uses references to Parent won't end up calling that implementation.
Note that with the code as-is, you should get a compile-time warning advising you to add the new modifier to the method in ChildSubclass:
public new void DisplayTitle() { ... }
You can't stop derived classes from hiding existing methods, other than by sealing the class itself to prevent the creation of a derived class entirely... but callers which don't use the derived type directly won't care.
What's your real concern here? Accidental misuse, or deliberate problems?
EDIT: Note that the warning for your sample code would be something like:
Test.cs(12,19): warning CS0108:
'ConsoleApplication1.ChildSubclass.DisplayTitle()' hides inherited
member 'ConsoleApplication1.Parent.DisplayTitle()'. Use the new keyword
if hiding was intended.
I suggest you turn warnings into errors, and then it's harder to ignore them :)
A derived class cannot override your method, you didn't declare it virtual. Note how that's very different in C# compared to Java, all methods are virtual in Java. In C# you must explicitly use the keyword.
A derived class can hide your method by using the same name again. This is probably the compile warning you are talking about. Using the new keyword suppresses the warning. This method does not in any way override your original method, your base class code always calls the original method, not the one in the derived class.
Use the sealed modifier to prevent subclasses from overriding your classes, properties, or methods. What isn't working when you use sealed?
http://msdn.microsoft.com/en-us/library/88c54tsw.aspx
I'm fairly certain that what you want is not possible in C# using method modifier keywords.
Sealed only applies when overriding a virtual method in an ancestor class, which then prevent further overriding.
I've implemented a singleton class and keep getting the warning that a method I'm writing is a 'new protected member declared in a seal class.' It's not affecting the build but I don't really want to ignore the warning in case it causes problems later on? I understand a sealed class is a class that cannot be inherited - so it's methods cannot be overridden, but I still don't get why the following code would give me the warning (is it due to the use of the singleton design?):
namespace WPFSurfaceApp
{
public sealed class PresentationManager
{
PresentationManager()
{
}
protected void MethodName()
{
}
public static PresentationManager Instance
{
get
{
return Nested.instance;
}
}
class Nested
{
// Explicit static constructor to tell C# compiler
// not to mark type as beforefieldinit
static Nested()
{
}
internal static readonly PresentationManager instance = new PresentationManager();
}
}
EDIT: The warning is regarding MethodName() method.
EDIT: Change public void MethodName() to protected void MethodName()
The warning is because protected does not make sense in a class that can't be inherited from. It will logically be exactly the same as private for a sealed class.
It's not an error, per se, but the compiler is trying to draw your attention to the fact that making it protected instead of private will provide you no benefit and may not be doing what you intended (if you intended it to be visible to a sub-class, which can't exist in a sealed class).
So, yes, you can safely ignore it, but it's logically inconsistent to have protected members in a sealed class.
MSDN Entry for Compiler Warning CS0628
It is obvious because it doesn't make any sense. What will be use of protected member if class cant be inherited
As MSDN Says
Types declare protected members so that inheriting types can access or
override the member. By definition, you cannot inherit from a sealed
type, which means that protected methods on sealed types cannot be
called.
Think about when you review code yourself. You see something that makes no sense as far as you can see. There are a few likely possibilities:
The developer has done something foolish.
The developer has done something too clever for its purpose to be obvious to you.
The developer did something reasonable that no longer makes sense due to changes that took place in the mean time.
The developer did something that makes no sense yet, but will if a planned change happens.
In the first case, they should fix it.
In the second case, they should document it.
In the third case, they should change it; it'll make little practical difference but the code will make more sense and it may have some minor performance benefit.
In the fourth case, they should document it for the time being, and either make that change or back out of it sooner rather than later.
Either way, you would want to discuss it with them.
It's the same here, it makes no sense to add a protected member to a sealed class. I've no idea why you did it, and can't decide which of the four cases above applies, but one of them does. The warning highlights this. Do whichever of the four actions applies according to which of the four cases is in effect.
I say your are playing with C#. Seriously !!
In a static class, it is said that we can't declare protected members as static classes cannot be instantiated. In fact, when we write protected members in static classes it will throw an error during the build.
In a sealed class, it will throw a warning during the build. I guess like static classes, sealed classes should also give an ERROR and not a WARNING. If this difference should be there then why?
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...
}
}
This question really is kinda pointless, but I'm just curious:
This:
public sealed class MyClass
{
protected void MyMethod(){}
}
compiles, but gives a warning
while This:
public sealed class MyClass
{
public virtual void MyMethod(){}
}
doesn't compile. Just out of sheer curiosity, is there a reason for this?
virtual is used to declare a method/property "override-able".
sealed is used to declare that class cannot be inherited from.
So a virtual method in a sealed class could never be overridden, as the class could never be inherited from. It just doesn't make sense.
protected affects access to a member, it does not declare it "override-able" as virtual does (though it is often used in that manner) and is accordingly not contradictory.
The only reason I can think of is that sometimes you would need to write protected methods to override other protected methods. The language could have been designed to allow this:
protected override void Foo()
but not this
protected void Foo()
but that might have been seen to be a little hard to follow - it's the absence of override which makes it useless, whereas in the case of
public virtual void Foo()
it's the presence of virtual that is useless. The presence of something "wrong" is probably easier to understand than the absence of something useful.
In this case, being virtual may also have performance implications, whereas making something protected instead of private probably doesn't - so it's a bit more severe.
These are just guesses though really - if we're really lucky, Eric Lippert will give a more definitive answer. He's the one you want, not me :)
Best answer: treat warnings as errors and they're equivalent anyway ;)
I can't see a good reason for this. The protected MyMethod can be called from MyClass, but will never be called from a derived class (because MyClass is sealed). The virtual version is also allowed to be called directly from MyClass, but it is illegal for the method to have an override because you can't derive a class from MyClass...
A sealed class can have protected members via inheritance.
When a method is part of a class, it doesn't matter how that method got there.
In the first case, with the protected method on the sealed class, its the same as if the sealed class inherited a protected method. So it compiles.
Out of curiosity, what exactly is the warning given?
The error is:
CS0549: 'function' is a new virtual member in sealed class 'class'.
First of all, despite the fact that it doesn't really make sense to include new protected or virtual members in a sealed class, the CLI¹ does allow it. The CLI also allows calling members of a sealed class using the callvirt IL instruction, even though a compiler could freely replace it with the call instruction.
Currently, I can't find anything in ECMA-334 (C# Language Specification) that requires the compiler emit the above error. It appears like a Microsoft's implementation added the error just because it doesn't make sense to include new virtual members in a sealed class.
¹The CLI is a virtual machine, and the C# compiler emits byte code that runs on it. Almost any concept that's illegal in the CLI is also illegal in C# for that reason - but this is a case where C# does a little extra (not that it's a problem).
Edit: It seems to posts getting marked up are explaining why it doesn't make sense to write code like that in the OP. But regarding what rule made it a compiler error they appear to be wrong.
A sealed class cannot be sub-classed, therefore virtual is not an option. Thus error.
This first is a bit silly but valid, thus warning.
I'd guess the compiler does some optimizations with sealed classes that are impossible if you have a virtual method declared - "not having a vtable" seems a likely candidate.
That's just a guess, though.
As sealed When applied to a class, the sealed modifier prevents other classes from inheriting from it.
here i am trying to explain you one by one:
public sealed class MyClass
{
protected void MyMethod(){}
}
it gives you warning because practically it make no sense because after declaring a class as sealed you can't inherits it and as your method is protected so you can't access it outside the class using it's object(and keep also in mind that you can't create a child class of this so you can't use this method by that trick also).So practically it makes no sense to making it protected so compiler gives you a warning but if you make it as public or internal then it will not gives you error because it's useful in that case.
now the second one:
public sealed class MyClass
{
public virtual void MyMethod(){}
}
as you sealed you class and now you are making your method as virtual so indirectly you are giving a offer to someone to override it and that can be only possible by inheritance and here comes the issue.That you class is sealed so you can't perform inheritance with this class.so that's why with virtual it gives error.
i hope it will help you to understand.
for reference http://msdn.microsoft.com/en-us/library/88c54tsw.aspx
Declaring a new protected member implies an intent to share that member with descendent classes. A sealed class cannot have descendents, so declaring a new protected member is a bit of an oxymoron, just as declaring a new virtual method in a sealed class.
As for why virtual produces an error while protected only produces a warning, I can only speculate that perhaps it has to do with the fact that new virtual methods require the compiler to build data structures for the type (a vtable), whereas new protected members only have an access flag set - no new data structure. If the compiler is prohibited from creating a vtable for a sealed class, what should it do if it encounters a new virtual method? Fail the compile. A new protected method in a sealed class is pointless but doesn't required the compiler to venture into forbidden territory.