I've read this similar question I don't expect the same behavior as the OP and I don't really understand him but I have a usage for protected members inside the derived classes.
In Why is the 'this' keyword required to call an extension method from within the extended class Eric Lippert wrote:
... If you are in the scenario where you are using an extension method for a type within that type then you do have access to the source code. Why are you using an extension method in the first place then?
... Given those two points, the burden no longer falls on the language designer to explain why the feature does not exist. It now falls on you to explain why it should. Features have enormous costs associated with them.
...
So I will try to explain why I would expect a behavior and it's usage example.
The feature:
- A programer can access protected member of
this
object inside extension method. - When a protected member is used within extension method, you can only use the method inside classes derived from type of
this
object. - Protected extension method can be called only with
this
argument object which is the same object that is accessible bythis
keyword in caller method.
Real life usage scenario:
I'm playing with creating a Visual Studio custom editor based on WPFDesigner_XML example. Currently I'm trying to figure things out in class with following signature:
public sealed class EditorPane : WindowPane, IOleComponent, IVsDeferredDocView, IVsLinkedUndoClient
{...}
Lot of methods are using services Like this:
void RegisterIndependentView(bool subscribe)
{
IVsTextManager textManager = (IVsTextManager)GetService(typeof(SVsTextManager));
if (textManager != null)
{
if (subscribe)
{
textManager.RegisterIndependentView(this, _textBuffer);
}
else
{
textManager.UnregisterIndependentView(this, _textBuffer);
}
}
}
I like to keep focus on things that actually matter so I wrote helper method to simplify such methods. For example:
private void RegisterIndependentView(bool subscribe) {
if (with(out IVsTextManager tm)) return;
if (subscribe) tm.RegisterIndependentView(this, _textBuffer);
else tm.UnregisterIndependentView(this, _textBuffer);
}
The with
method look like this:
private bool with<T>(out T si) {
si = (T)GetService(getServiceQueryType<T>());
return si == null ? true : false;
}
And I placed getServiceQueryType<T>()
in a static class:
public static class VSServiceQueryHelper {
public static Type getServiceQueryType<T>() {
var t = typeof(T);
if (!serviceQueryTypesMap.ContainsKey(t)) throw new Exception($@"No query type was mapped in ""{nameof(serviceQueryTypesMap)}"" for the ""{t.FullName}"" interface.");
return serviceQueryTypesMap[t];
}
private static Dictionary<Type, Type> serviceQueryTypesMap = new Dictionary<Type, Type>() {
{ typeof(IVsUIShellOpenDocument), typeof(SVsUIShellOpenDocument) },
{ typeof(IVsWindowFrame), typeof(SVsWindowFrame) },
{ typeof(IVsResourceManager), typeof(SVsResourceManager) },
{ typeof(IVsRunningDocumentTable), typeof(SVsRunningDocumentTable) },
{ typeof(IMenuCommandService), typeof(IMenuCommandService) },
{ typeof(IVsTextManager), typeof(SVsTextManager) },
};
}
This works well but I would also like to place the with
method inside VSServiceQueryHelper
as an extension so any time I would extend WindowsPane
i could just place using static com.audionysos.vsix.utils.VSServiceQueryHelper;
at the top and use the with
method that is already implemented.
The problem:
I can't make with
method an extension because the GetService
method used by it is a protected member of the WindowsPane
which is the base type of my class. So now I need to place with
implementation in every class that extends WindowPane
and this breaks the rule of never repeat yourself :/