Let's say I have an interface with a read-only property and and a concrete class where the property is instantiated in the constructor and marked as read-only.
internal interface IExample
{
ObservableCollection<string> Items { get; }
}
internal class Example : IExample
{
private readonly ObservableCollection<string> _items;
public Example()
{
_items = new ObservableCollection<string>();
}
public ObservableCollection<string> Items
{
get { return _items; }
}
}
When I use the interface Resharper warns me that I might have a possible null reference in calling code.
public class ExampleWithWarnings
{
public void Show()
{
IExample example = new Example();
// resharper warns about null reference
example.Items.Add( "test" );
}
}
I realize that by definition the interface doesn't guarantee that the property will have a value. (I also recognize that properties on interfaces aren't ideal). But I know this property will always have a value.
Is there any magic attribute that I can put on the interface that would prevent Resharper from showing a warning? I'd rather not have to decorate all usages of the class with a disable pragma warning.
Yes, there is an attribute you can use: JetBrains.Annotations.NotNullAttribute. But you don't need to add a reference to ReSharper in your project. You can use your own implementation: open the ReSharper options, and under Code Inspection > Code Annotations you will find a "Copy default implementation to clipboard". Now just paste that into a code file in your project. You can even change the namespace.
And then slap the attribute in the interface property.
You should also have a look under Code Inspection > Settings and pick "Assume entity can be null... when entity is explictly marked with CanBeNull attribute, or checked for null". This way you only get warnings in the members you explicit mark as troublesome.
You can reduce this warning to a suggestion. You could also edit the external annotation files to create custom rules or behavior: http://msmvps.com/blogs/peterritchie/archive/2008/07/21/working-with-resharper-s-external-annotation-xml-files.aspx
Related
Cli interface looks like this:
using namespace System::Timer
namespace Interfaces
{
public interface class ITimerProvider
{
property Timer AppTimer
{
Timer get();
}
}
}
Getting to a c# class deriving from that interface and using "implement interface" from right-click menu in VS2013, it creates:
public void get_AppTimer(ref Timer value)
{
throw new NotImplementedException();
}
The compiler complains "MyProject does not implement interface member MyCLIProject.Interfaces.ITimerprovider.get_AppTimer()"
It does so, even when it has put it inside by itself.
Hans has given the answer. Correcting interface declaration leads to expected auto-generated code and the project compiles fine:
property Timer^ AppTimer
{
Timer^ get();
}
I think this might be due to Visual Studio not generating the code correctly for you.
While technically properties are just syntactic sugar for the methods get_propertyName() and set_PropertyName(), you don't actually write those methods in C# when implementing a property. The correct C# code for implementing the property would be this:
class MyProject
{
public Timer AppTimer
{
get
{
// return the value here
}
}
}
If you change your code to something like this, that should fix the error.
I have a class with a member that I need to keep for legacy code and I need to mark it as obsolete so that new code doesn't use it (without getting a warning).
Let's say the class looks like this:
class MyClass
{
[Obsolete]
private string _old = "...";
[Obsolete]
public string Old
{
get { return _old; }
}
}
I'm declaring that the member field _old is obsolete to make sure that new code inside the class do not use that field.
I'm also declaring that the property Old is obsolete to make sure that code outside of the class do not use the property.
When I compile this I get a warning in the property getter saying that _old is obsolete. I thought that the compiler would silently ignore this since the property itself is obsolete.
Am I missing something or do I need to add #pragma warning disable/restore for obsolete member fields everywhere they're used (even though the method/property itself is marked as obsolete)?
The reason that "I thought that the compiler would silently ignore this" is because it seems to do so for obsolete classes:
[Obsolete]
public class MyObsoleteClass
{
public string DoSomething()
{
// No warning here, since the class itself is obsolete
return new MyClass().Old;
}
}
As #Heinzi answered: this seems to be due to a bug in Visual Studio. I've filed a report on connect:
https://connect.microsoft.com/VisualStudio/feedback/details/1146809
It turns out that the bug in Visual Studio is not just limited to accessing an obsolete field from a property.
Accessing an obsolete property from an obsolete method should not yield a warning:
public class Class2
{
[Obsolete]
public string Property { get; set; }
[Obsolete]
public void Method()
{
this.Property = "value"; // <-- Incorrect warning reported
}
}
Neither should doing so from another class:
public class Class3
{
[Obsolete]
public string Property { get; set; }
}
public class Class4
{
[Obsolete]
public string Method()
{
return new Class3().Property; // <-- Incorrect warning reported
}
}
Interestingly, it works in the following class and when adding this class the other warnings (from Class4 and Class2) will magically disappear.
public class Class5
{
[Obsolete]
public void Method()
{
// No warning reported here, which is good.
// This magically makes the other warnings disappear too!
new Class2().Method();
}
}
Your code is fine, and your understanding of how the Obsolete attribute should work is correct: If you look at the "Output" tab after compilation, you will note that the compiler does not output a warning for your case (but will output a warning if you remove the Obsolete attribute from your property, as expected).
You are right, though, that Visual Studio sometimes displays a warning after making arbitrary changes to the code. This seems to be a bug in Visual Studio. If you can still reproduce it with the most current version, I would suggest that you file a bug report on http://connect.microsoft.com.
This would be a clever feature, but I don't see any indication in the documentation that it should work this way. On the other hand I would not use the Obsolate attribute on a private member (if the class is not extremly huge), but I would refactor it instead. I your case I would write this:
class MyClass
{
[Obsolete]
public string Old
{
get; private set;
}
}
And then you only need to change the usages of _old to Old and the problem is solved.
Here is some code:
class Program
{
static void Main(string[] args)
{
MyClass class1 = new MyClass();
MyOtherClass class2 = new MyOtherClass();
Helper.UseAttribute<MyClass>(class1);
//Raise a warning to tell the developer that they cannot use this class
//as there is no property with the specified attribute.
Helper.UseAttribute<MyOtherClass>(class2);
}
}
public class MyAttribute : System.Attribute { }
class MyClass
{
[MyAttribute]
public string SomethingAwesome { get; set; }
}
class MyOtherClass
{
public string SomethingElseWhichIsAlsoPrettyAwesome { get; set; }
}
static class Helper
{
public static void UseAttribute<T>(T sender)
{
//Do something with the property that has MyAttribute
//If there isn't a property with this attribute, then raise
//a warning.
}
}
In an ideal scenario, I want to restrict a developer from passing classes to a method which do not have a certain attribute.
I am aware that I can use an interface, or a base class of some description, however the question really is whether something like the example above is possible.
If you're happy to either use the VS 2015 preview or wait until VS 2015 is out, you can use Roslyn for this.
You'd write a DiagnosticAnalyzer class, probably registering a syntax node analyzer to specifically look for invocations of Helper.UseAttribute<T>. When you find such a use, you'd find the symbol for T and check whether there are any properties with the MyAttribute attribute applied to it, and raise a warning if not. This warning will be shown in Visual Studio itself, as well as applying on CI builds (assuming you register the analyzer assembly appropriately).
It takes a while to get started with the Roslyn diagnostic APIs, but once you're used to it, it's really powerful.
Of course, another option is to throw an exception at execution time, and rely on there being unit tests around all callers so that you'd be able to catch it when they fail :) You should probably do that as well as adding compile-time support via Roslyn.
Best you can do right now is to handle it on runtime (and throw an exception or something). On design-/compiletime I think there is no possibility yet.
public static void UseAttribute<T>(T sender)
{
var hasAttribute = typeof(T).GetProperties().Any(prop => Attribute.IsDefined(prop, typeof(MyAttribute)));
if (!hasAttribute)
throw new Exception("Does not contain attribute");
}
Let say I have a class like this:
public class A
{
private BaseSettings fieldA;
public ISettings PropertyA
{
get {return fieldA;}
set {fieldA= value as BaseSettings;}
}
}
where BaseSettings implements ISettings. Inside class A, if I want to access BaseSettings' property called PropertyB, which of this is a good practice:
fieldA.PropertyB;
or
((BaseSettings)PropertyA).PropertyB;
One may say the first approach may hide the hint to when a property changed. For example, a code may listen to PropertyChangedEvent and then the value for property changed without raising the event.
Another one may say the second approach may expose a risk that when a person who is not familiar with current code modify it, he may cast the PropertyA to different type that implements ISettings.
Both approaches have its downside. In a good programming practice, which one should be more preferable?
EDIT:
Added based on the comments belows:
I agree that setting the backing-field as ISettings makes absolute sense. But what should I do to make sure that the PropertyA is always type of BaseSettings. That will raise a question: "Then why don't you set both property and backing-field to BaseSettings?".
The reason behind why property and its backing field are different is that class A also implement an interface like this
public interface IControlWithSettings
{
ISettings OwnerSettings
{
get;
set;
}
ISettings Settings
{
get;
set;
}
}
So the actual classA would look like this
public class BaseForm: Form, IControlWithSettings
{
private BaseFormSettings settings;
public ISettings Settings
{
get {return settings;}
set {settings= value as BaseFormSettings;}
}
}
And I have another class B would also implement IControlWithSettings
public class BaseUserControl: UserControl, IControlWithSettings
{
private BaseUserControlSettings settings;
public ISettings Settings
{
get {return settings;}
set {settings= value as BaseUserControlSettings ;}
}
}
Both BaseFormSettings : ISettings and BaseUserControlSettings : ISettings . This is actual ISettings interface
public interface ISettings
{
Dictionary<string, ISettings> Children { get; set; }
}
the 'as' casting is a side effect I put into the setter so that it will ignore and return null if the setting is set to wrong one. I read somewhere saying I shouldn't throw exception in a setter. So making it null is my way to inform there is something wrong has been done.
So what is the better approach. Did I design it wrong?
As you stated, both approaches have their downsides, and it also depends on whether the property setter may contain some additional logic (e.g. validation), and you may use or circumvent this additional logic from inside the class.
If there's nothing that speaks against it, I'll use direct access to the field. It's neater and it avoids all this typecasting stuff.
But generally: Why would you back your property with the derived type, while the property itself has the interface type? This doesn't make much sense. Why not just:
public class A
{
public ISettings PropertyA { get; set; }
}
This would be much cleaner, and your question wouldn't even arise.
Edit (based on the answer's edit)
In case of the 'double use' of the backing field the typecasting makes sense. But I don't think (and never heard that before) that it's a bad thing to throw an exception from a property setter. On the contrary: Validating a value and throwing an exception if it doesn't pass is a very common pattern.
So, in your concrete case, I would validate the value for the correct type, throw if it's not correct, and use the backing field internally to bypass this type check.
I am getting a code analysis warning that seems to be a false-positive.
CA1812 : Microsoft.Performance : 'MyClass.MyPrivateClass' is an internal class that is apparently never instantiated. If so, remove the code from the assembly. If this class is intended to contain only static methods, consider adding a private constructor to prevent the compiler from generating a default constructor.
How do I get rid of this warning? I prefer to not suppress warnings unless I am sure I couldn't avoid it otherwise.
The classes look like this:
namespace Some.Namespace
{
public class MyClass
{
private class MyPrivateClass
{
public int Id { get; set; }
public ModelObject { get; set; }
}
}
}
I use it like this:
private IQueryable<MyPrivateClass> GetMyPrivateClasses()
{
return this.Repository().All()
.Select(m => new MyPrivateClass { Id = m.Id, ModelObject = m };
}
Does this usage not count as instantiation?
I guess it is examining the IL; and genuinely - that IL does not ever contain a new MyPrivateClass instruction - because that statement is presumably running against IQueryable<T>, hence that lambda is an expression tree. It will contain some Expression.New, and some typeof(MyPrivateClass) - but no new MyPrivateClass.
In this case, the error is misleading. Simply suppress it.
FYI there is a new documentation page for this warning:
https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/quality-rules/ca1812
Instantiation of classes is not always recognized by analyzers.
Suppress this warning, if justified:
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1812:AvoidUninstantiatedInternalClasses", Justification = "generic/late bound/reflection")]
Happens especially in Net.Core.
Change your class to internal or public, that solves the problem. Anyway, you can extract your inner class from the outer class...