C# 隐藏继承的成员
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1528/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Hiding inherited members
提问by MojoFilter
I'm looking for some way to effectively hide inherited members. I have a library of classes which inherit from common base classes. Some of the more recent descendant classes inherit dependency properties which have become vestigial and can be a little confusing when using IntelliSenseor using the classes in a visual designer.
我正在寻找某种方法来有效地隐藏继承的成员。我有一个从公共基类继承的类库。一些较新的后代类继承了依赖属性,这些属性已经变得残留并且在使用IntelliSense或在可视化设计器中使用这些类时可能会有些混乱。
These classes are all controls that are written to be compiled for either WPF or Silverlight 2.0. I know about ICustomTypeDescriptor
and ICustomPropertyProvider
, but I'm pretty certain those can't be used in Silverlight.
这些类都是为 WPF 或 Silverlight 2.0 编写的所有控件。我知道ICustomTypeDescriptor
and ICustomPropertyProvider
,但我很确定那些不能在 Silverlight 中使用。
It's not as much a functional issue as a usability issue. What should I do?
与其说是可用性问题,不如说是功能问题。我该怎么办?
Update
更新
Some of the properties that I would really like to hide come from ancestors that are not my own and because of a specific tool I'm designing for, I can't do member hiding with the new
operator. (I know, it's ridiculous)
我真正想隐藏的一些属性来自不是我自己的祖先,并且由于我正在设计的特定工具,我无法使用new
操作员进行成员隐藏。(我知道,这很可笑)
采纳答案by caryden
Override them like Michael Suggests aboveand to prevent folks from using the overridden (sp?) methods, mark them as obsolete:
像上面迈克尔建议的那样覆盖它们并防止人们使用覆盖的(sp?)方法,将它们标记为过时:
[Obsolete("These are not supported in this class.", true)]
public override void dontcallmeanymore()
{
}
If the second parm is set to true, a compiler error will be generated if anyone tries to call that method and the string in the first parm is the message. If parm2 is false only a compiler warning will be generated.
如果第二个参数设置为 true,如果有人尝试调用该方法并且第一个参数中的字符串是消息,则会生成编译器错误。如果 parm2 为 false,则只会生成编译器警告。
回答by Michael Stum
While you cannot prevent usage of those inherited members to my knowledge, you should be able to hide them from IntelliSense using the EditorBrowsableAttribute:
虽然据我所知,您无法阻止使用这些继承的成员,但您应该能够使用EditorBrowsableAttribute将它们从 IntelliSense 中隐藏起来:
Using System.ComponentModel;
[EditorBrowsable(EditorBrowsableState.Never)]
private string MyHiddenString = "Muahahahahahahahaha";
Edit:Just saw this in the documentation comments, which makes it kinda useless for this purpose:
编辑:刚刚在文档评论中看到了这一点,这使得它对此毫无用处:
There is a prominent note that states that this attribute "does not suppress members from a class in the same assembly". That is true but not complete. Actually, the attribute does not suppress members from a class in the same solution.
有一个突出的注释指出该属性“不会抑制来自同一程序集中的类的成员”。这是真的,但并不完整。实际上,该属性不会抑制同一解决方案中类的成员。
回答by Karl Seguin
I think you're best least hackish way is to consider composition as opposed to inheritance.
我认为你最好的最简单的方法是考虑组合而不是继承。
Or, you could create an interface that has the members you want, have your derived class implement that interface, and program against the interface.
或者,您可以创建一个具有所需成员的接口,让您的派生类实现该接口,然后针对该接口进行编程。
回答by Mike Stone
One potential thing you can do is contain the object rather than extend from the other class. This will give you the most flexibility in terms of exposing what you want to expose, but if you absolutely need the object to be of that type it is not the ideal solution (however you could expose the object from a getter).
您可以做的一件事是包含对象而不是从另一个类扩展。这将在公开您想要公开的内容方面为您提供最大的灵活性,但是如果您绝对需要该类型的对象,这不是理想的解决方案(但是您可以从 getter 公开对象)。
Thus:
因此:
public class MyClass : BaseClass
{
// Your stuff here
}
Becomes:
变成:
public class MyClass
{
private BaseClass baseClass;
public void ExposeThisMethod()
{
baseClass.ExposeThisMethod();
}
}
Or:
或者:
public class MyClass
{
private BaseClass baseClass;
public BaseClass BaseClass
{
get
{
return baseClass;
}
}
}
回答by Nathan Wheeler
I know there's been several answers to this, and it's quite old now, but the simplest method to do this is just declare them as new private
.
我知道对此有几个答案,现在已经很老了,但最简单的方法就是将它们声明为new private
.
Consider an example I am currently working on, where I have an API that makes available every method in a 3rd party DLL. I have to take their methods, but I want to use a .Net property, instead of a "getThisValue" and "setThisValue" method. So, I build a second class, inherit the first, make a property that uses the get and set methods, and then override the original get and set methods as private. They're still available to anyone wanting to build something different on them, but if they just want to use the engine I'm building, then they'll be able to use properties instead of methods.
考虑我目前正在研究的一个示例,其中我有一个 API,它使 3rd 方 DLL 中的每个方法都可用。我必须采用他们的方法,但我想使用 .Net 属性,而不是“getThisValue”和“setThisValue”方法。因此,我构建了第二个类,继承了第一个类,创建了一个使用 get 和 set 方法的属性,然后将原始 get 和 set 方法覆盖为私有方法。任何想要在其上构建不同内容的人仍然可以使用它们,但是如果他们只想使用我正在构建的引擎,那么他们将能够使用属性而不是方法。
Using the double class method gets rid of any restrictions on being unable to use the new
declaration to hide the members. You simply can't use override
if the members are marked as virtual.
使用双类方法摆脱了无法使用new
声明来隐藏成员的任何限制。override
如果成员被标记为虚拟,您根本无法使用。
public class APIClass
{
private static const string DllName = "external.dll";
[DllImport(DllName)]
public extern unsafe uint external_setSomething(int x, uint y);
[DllImport(DllName)]
public extern unsafe uint external_getSomething(int x, uint* y);
public enum valueEnum
{
On = 0x01000000;
Off = 0x00000000;
OnWithOptions = 0x01010000;
OffWithOptions = 0x00010000;
}
}
public class APIUsageClass : APIClass
{
public int Identifier;
private APIClass m_internalInstance = new APIClass();
public valueEnum Something
{
get
{
unsafe
{
valueEnum y;
fixed (valueEnum* yPtr = &y)
{
m_internalInstance.external_getSomething(Identifier, yPtr);
}
return y;
}
}
set
{
m_internalInstance.external_setSomething(Identifier, value);
}
}
new private uint external_setSomething(int x, float y) { return 0; }
new private unsafe uint external_getSomething(int x, float* y) { return 0; }
}
Now valueEnum is available to both classes, but only the property is visible in the APIUsageClass class. The APIClass class is still available for people who want to extend the original API or use it in a different way, and the APIUsageClass is available for those who want something more simple.
现在 valueEnum 可用于两个类,但只有该属性在 APIUsageClass 类中可见。APIClass 类仍然适用于想要扩展原始 API 或以不同方式使用它的人,而 APIUsageClass 则适用于那些想要更简单的人。
Ultimately, what I'll be doing is making the APIClass internal, and only expose my inherited class.
最终,我要做的是将 APIClass 设置为内部,并且只公开我继承的类。
回答by Pavel Jounda
I tested all of the proposed solutions and they do not really hide new members.
我测试了所有建议的解决方案,它们并没有真正隐藏新成员。
But this one DOES:
但这个确实:
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public new string MyHiddenProperty
{
get { return _myHiddenProperty; }
}
But in code-behide it's still accessible, so add as well Obsolete Attribute
但是在代码隐藏中它仍然可以访问,因此也添加过时属性
[Obsolete("This property is not supported in this class", true)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public new string MyHiddenProperty
{
get { return _myHiddenProperty; }
}
回答by Robert
To fully hide and mark not to use, including intellisense which I believe is what most readers expect ...
完全隐藏和标记不使用,包括智能感知,我相信这是大多数读者所期望的......
[Obsolete("Not applicable in this class.")]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
[Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
回答by acon
You can use an interface
你可以使用一个接口
public static void Main()
{
NoRemoveList<string> testList = ListFactory<string>.NewList();
testList.Add(" this is ok ");
// not ok
//testList.RemoveAt(0);
}
public interface NoRemoveList<T>
{
T this[int index] { get; }
int Count { get; }
void Add(T item);
}
public class ListFactory<T>
{
private class HiddenList: List<T>, NoRemoveList<T>
{
// no access outside
}
public static NoRemoveList<T> NewList()
{
return new HiddenList();
}
}
回答by Sam
While clearly stated above that it is not possible in C# to change the access modifiers on inherited methods and properties, I overcame this issue through a sort of "fake inheritance" using implicit casting.
虽然上面明确指出在 C# 中不可能更改继承的方法和属性的访问修饰符,但我通过使用隐式转换的一种“假继承”克服了这个问题。
Example:
例子:
public class A
{
int var1;
int var2;
public A(int var1, int var2)
{
this.var1 = var1;
this.var2 = var2;
}
public void Method1(int i)
{
var1 = i;
}
public int Method2()
{
return var1+var2;
}
}
Now lets say you want a class B
to inherit from class A
, but want to change some accessibility or even change Method1 entirely
现在假设您想要class B
继承自class A
,但想要更改某些可访问性甚至完全更改 Method1
public class B
{
private A parent;
public B(int var1, int var2)
{
parent = new A(var1, var2);
}
int var1
{
get {return this.parent.var1;}
}
int var2
{
get {return this.parent.var2;}
set {this.parent.var2 = value;}
}
public Method1(int i)
{
this.parent.Method1(i*i);
}
private Method2()
{
this.parent.Method2();
}
public static implicit operator A(B b)
{
return b.parent;
}
}
By including the implicit cast at the end, it allows us to treat B
objects as A
s when we need to. It can also be useful to define an implicit cast from A->B
.
通过在最后包含隐式强制转换,它允许我们在需要时将B
对象视为A
s。定义从 的隐式转换也很有用A->B
。
The biggest flaw to this approach is that you need to re-write every method/property that you intend to "inherit". There's probably even more flaws to this approach, but I like to use it as a sort of "fake inheritance".
这种方法的最大缺陷是您需要重新编写您打算“继承”的每个方法/属性。这种方法可能有更多的缺陷,但我喜欢将它用作一种“假继承”。
Note:
笔记:
While this allows for changing the accessibility of public
properties, it doesn't solve the issue of making protected
properties public.
虽然这允许更改public
属性的可访问性,但并不能解决将protected
属性设为公开的问题。