Mark standard library method as `Obsolete` or otherwise "hiding" it - c#

String.Contains optionally takes a StringComparison enum (e.g. StringComparison.OrdinalIgnoreCase). I keep forgetting to specify IgnoreCase, so I want to mark that method as [Obsolete] so I see it in Warnings so I remember to specify the kind of StringComparison.
I'm open to other solutions too, like doing something to "hide" that method and prevent it from being called. The ideal solution doesn't involve Roslyn analyzers though, as I'm using F#.
This solution is interesting, but obviously not ideal.

I would use an Extension Method. Just put it somewhere that's available to all your code, and declare it directly in the System namespace. (I'm not fluent in F#, but this should work.)
namespace System
type String with
member CaselessContains(str) = String.Contains(str, StringComparison.OrdinalIgnoreCase)

Ionide for VS Code supports analyzers. You'd have to write one for the methods you want to disallow.

Related

Extension Methods forward compatible

With extension methods we can easily add methods to any type. Obviously this opens the possibility in a future version of .net the extension method could no longer get called (for example the type now includes a method with identical signature to the extension method).
Should this be a concern?
If so, how should I deal with this and design my extension methods as to minimise code changes should this happen?
If the framework is changed so much in the future, there will always be compatibility issues. If a new framework method is added with the same name as your extension method, it is quite likely that they have the same, or at least very similar functionality and a refactoring is due anyways.
I think that the power of the extension methods is too large to ignore just because of this risk.
I'm afraid that the only thing you can do is providing unique enough names to your extension methods so you're 100% sure you will never have a conflict.
Not talking about adding the name of your cat to the method's name, just try to be more creative :)
Use obscure method names that would never be used in the framework.
edit -- perhaps obscure wasn't the most appropriate word, please substitute with meaningful but less common verbage
Attempting to avoid signature conflicts is really the only strategy to avoiding the hassle of code rework (assuming the functionality of the extension method needs to be preserved and not simply converted to the framework's definition of the method).

Attributes, just metadata or needed?

Few days ago I asked what this attribute means:
[System.Runtime.InteropServices.DllImport("KERNEL32.DLL", EntryPoint="RtlZeroMemory")] public unsafe static extern bool ZeroMemory(byte* destination, int length);
I have learned that attributes are metadata but what I do not understand is - is this needed in this case? I thought metada are just that, metadata that can be ommited. Also the code seems to be running fine when I remove the attibute.
I would like to understand.
PS: Hans Passant mentioned its covered by any book about .NET Csharp..it is not, the largely used one VS 2010 from John Sharp does not cover it.
The metadata does usually have a reason and a meaning. In this particular case it tells the compiler how to bind this external method definition (e.g. to which DLL import it matches).
Other attributes control how interop is performed by the framework, yet other control how the object inspector displays data. 3rd-party attributes are also used extensively to control various behaviors, for instance for finding specific type information when performing reflection.
No, this attribute is absolutely required. It informs the CLR that what you've defined actually uses platform invokation services (or, P/Invoke) to call a function defined in unmanaged code.
Specifically, the RtlZeroMemory function, defined in the library kernel32.dll.
Without it, the compiler wouldn't know which function it was bound to, and the CLR wouldn't know which function to call at run-time.
This attribute is doing 2 things
Informs the CLR that the C method being invoked lives in kernel32.dll
Informs the CLR that the C method name is RtlZeroMemory and not ZeroMemory as it's named in code.
Yes this attribute is 100% necessary. It's a requirement for any PInvoke method to at the least name the DLL the C method lives in.
As your example shows, attributes are in fact needed in several key areas of .NET programming.
Attributes provide a model known as "Aspect-Oriented Programming" or AOP. Instead of having to write code that performs some specific task, such as serialization, DLL interop, logging, etc, you can instead simply decorate the classes or members on which you want these tasks performed with an attribute. Attributes are a special type of class, with members which can be invoked by the CLR as it runs your code, that will perform the task you wanted when you decorated the code.
You are correct in part; many attributes are intended simply to store metadata. DescriptionAttribute is a good one. However, even in this case, the attribute is important depending on how it's used. If you are decorating a member of a GUI class that you want to use in the designer, [Description()] provides valuable information to the user of the class in the designer, which may not be you. I've also seen and used many alternate uses for DescriptionAttribute; it can be applied to almost anything, so I've used it to provide "friendly names" for Enum constants, coupled with a GetDescription() extension method to grab them, when using Enums to populate drop-down lists.
So, while it's technically "metadata", an attribute's being "required" is governed by how much you want the task inherent in that attribute to be performed.
As for this particular attribute, I'm not too sure. To be honest, I've never seen it in almost a year of constant C#.
However, attributes in general can prove very useful. For instance, I was having issues with the VS2010 designer setting autocomplete properties in the wrong order, and getting run-time errors as a result. The solution was to add attributes to the autocomplete properties that prevented the designer from writing these properties to the design file, and instead setting the properties myself in the .cs file (in the proper order).
Summary: Attributes (usually) are not required, but can prove extremely useful.

Are C# extension methods only available for instance methods?

I have recently started to make useful use of C# extension methods. The SO examples and the documentation suggest that they are only used for instance methods (i.e. with the this keyword). It is possible to use them (or another approach) with static/class methods?
(My particular requirement is converting Java code to C# where "most of the code" does not need editing. The Java instance methods (e.g. Java String.indexOf()) can be routed through an extension method calling C# string.IndexOf()). I would like to do the same for, say, Java Math.abs() => C# Math.Abs()).
SUMMARY No. The answers suggest it would be a reasonable thing to have but it's unlikely to happen soon. Workarounds will require editing creating new classes or something similar and may not be worth it.
You cannot create static extension methods - it's also something I've wished to be able to do!
You could create your own static classes with a standard suffix, i.e. MathJSyntax.abs(..) which would call Math.Abs(..)
C# 3.0 does not allow the creation of static extension methods, unfortunately. F# however does allow this, along with the much desired feature of extension properties.
The notation itself doesn't let you do it, the "this" class parameter expects an instance to the class to be passed in. If they intended to at least eventually add it, they wouldn't have written it like that.
So the short answer is nope, and never will be!

C#: Discovering Extension Methods

What tools or techniques do you recommend for discovering C# extension methods in code? They're in the right namespace, but may be in any file in the solution.
Specifically:
How can I find all extension methods (and navigate to them) on the current type in the code window?
I do have Resharper (v4), so if that has a mechanism I'm not aware of - please share!
If you have the source then you can search for this Type identifier using regular expressions. Considering the fact that it has to be the first parameter to the function something like this should do the trick:
\(this:b+:i:b+:i
At least this way you can discover where the extensions methods are defined and add that namespace, then rely on intellisense. Just ran this on a non-trivial project with lots of extensions methods everywhere and it worked a treat. The only false positive was something like this:
if(this is Blah...
Which we can fix by adding static to our search since the extension methods have to be static:
static.*\(this:b+:i:b+:i
This won't work for cases like this:
public
static ExtensionMethod(
this int
iVal) {
}
But that's kind of the limitation of regular expressions. I am sure certain somebodies can tell you all about the pain of using regular expressions to parse a language.
Now, what I think is missing from the IDE is the ability to recognise the extension methods that are in a non-imported namespace. Similar to when you know the classname, if you type it up, the IDE will give you a hint to either use it explicitly or import the namespace. After all, that's how I import all my namespaces and frequently find myself trying to do the same to extension methods.
This is pretty low-tech, but how about Ctrl-F searching for "this:b+MyClassName" ?
If you are using VS which I guess you are intellisense will show all the avialable extensionmethod for a given object for you (marked with a blue thingy added to the usual instance method icon). That list might differ from file to file (a mthod called aMethod might mean two different things in two different files) eventhough the object type is the same (which is based on the way extension methods are found)
If you've got resharper, just hold down the ctrl key and click on the method.
If you have installed the ILSpy extension in Visual Studio (I am using 2022) then you can:
Right click on the class/type and select -> Open code in ILSpy
In ILSpy right click on the type and select -> Analyze
In the Analyze window you will see a node "Extension methods" (if any exists, else no node is shown)

Finding unused enum members

What is the quickest way to determine which members of an enum are not being used?
Comment the enum members out one by one and see if your code compiles. If compilation breaks, the member is used. Although this method only catches compile-time use of your enums. They could be used at runtime.
If you're using ReSharper, click on the enum to check, hit Alt+F7 (Shift+F12 if you're using VS shortcuts), and it'll give you a list of every place it's used in your entire solution.
Being on the safe side you can mark your members with ObsoleteAttribute. Adding [Obsolete(true)] will fail the build if given member is used.
This can obviously be used not only for enums but for nearly anything in .NET.
Resharper is your tool of choice if you need to delete the members from a solution and you're not worried about another uses in different solutions.
Using find references on each member of the enum is the fastest way I can think of.
Ctrl-F and search the entire namespace/project for that member of enum
If you are using VS2005/8 Ctrl-Shift-F so search in the files. This will give you a list of files that you can double-click to goto the lines.
If you don't use VS then you can use WinGrep which will do the same thing (without the double-click feature)
Commenting / uncommenting members. If the compiler does not throw an error the enum member is not used.
Update: As mentioned in the comments this of course only works for projects contained in the solution / the active build configuration. The same holds for the Find References and Ctrl+F methods.
Otherwise there is also the option to do a file search, e.g. using grep. However, this option only allows to do a string-based search and does not resolve any types.

Categories

Resources