我正在使用C#创建一个将广泛分发的.Net类库(DLL)。我有一个名为Value
的抽象类,我希望它有一个抽象的double
属性,也称为Value
,即
public abstract class Value {
// Only accessible by subclasses within the project.
internal Value() {}
public abstract double Value {
get;
}
}
但是C#编译器不允许这样做 - 我收到消息“成员名称不能与其封闭类型相同”,如here所述。
我知道最容易做的事情就是更改属性的名称或类的名称......但实际上我希望这些名称是这样的,我很乐意实现一个丑陋的破解得那样。只要它从使用此DLL的外部代码中正常工作即可。
与C#不同,VB.Net 将允许我定义一个与该类同名的属性,因此我正在研究将我的C#项目与一个定义{{{ 1}} class(和它的Value
属性)来制作一个DLL。这似乎并不像我希望的那样简单。
另一种选择是在VB中重写整个项目......不是很吸引人,但如有必要,我会考虑它。我更喜欢C#而不是VB.Net,但我的首要任务是以我想要的方式获取构建的DLL。
我想知道其他可能的选择。有什么想法可以解决这个问题吗?
编辑:从下面的评论中可以清楚地看到很多人对一个班级的“价值”这个名称并不怎么看......有人能解释为什么这么糟糕吗?我知道它不是很具描述性,但我认为它很适合我的项目。是因为它是C#中的一个关键字,用于属性设置器吗?答案 0 :(得分:8)
你不能直接这样做。但是,您可以考虑:
Value
成员的接口,并使用显式接口实现(调用者可以使用接口)Value()
方法,以便obj.Value()
正常工作Value
丑陋的黑客:
public abstract class ValueBase {
public abstract double Value { get; }
internal ValueBase() {}
}
public abstract class Value : ValueBase {
internal Value() {}
}
public sealed class ValueReal : Value {
public override double Value { get { return 123; } }
}
答案 1 :(得分:3)
如果您的班级代表双倍(除了一些额外的元数据),您可以选择转换运算符:
public abstract class Value
{
protected abstract double GetValue();
public static explicit operator double (Value value)
{
return value.GetValue();
}
}
然后,您的客户端代码可以访问元数据或将Value
类型的实例强制转换为double
。根据元数据和用法,您可以隐式转换,因此您不必进行显式转换,也可以定义从double
到Value
的转换。
System.Xml.Linq
程序集使用了类似的方法,例如,XElement
可以转换为任何基本类型,作为访问其“值”的方法。
答案 2 :(得分:2)
正如其他人所说,这在C#中是不可能的。
其他人批评名称Value
为一个类,虽然我同意它可能过于通用,但我可以看到可能有意义的情况。
请注意,如果Value
是一个抽象类,或许ValueBase
可能是一个体面的,一致的名字?许多.Net框架(特别是WPF)使用XxxBase
。
要考虑的另一个选择是在类名前加上项目名称,如FooValue。
答案 3 :(得分:2)
价值是一个类的可怕名称。它非常模糊,所以它没有描述一个值代表什么,它与保留的单词'value'冲突。您会发现自己正在使用value = Value.Value
,想知道为什么您的代码毫无意义,并最终尝试修复一个可怕的错误,这个错误直接导致使用'value'而不是Value或value或_value或this.value。当你必须存储另一种任意数字时会发生什么?你会称之为Value2吗?
使用更具体和更有意义的名称命名该类,问题将不再存在。不要修复症状 - 修复原因。
即使您只将其重命名为“DataValue”或“MySystemValue”,您也将为自己提供优质服务。
答案 4 :(得分:0)
对流行的观点鞠躬,我决定将Value
课程重命名为DataValue
。我对这个名字感到非常满意,这意味着我不需要任何黑客来获得名为Value
的属性。非常感谢大家的反馈。
但是,尽管有用的答案,我仍然认为这个问题没有得到理想的回答。所提议的解决方案都没有完全符合要求,或者至少没有副作用,例如对于其他多余的接口或公共类的要求。在我的问题中我可能更清楚一点,我非常高兴地考虑一个涉及不安全代码或修改中间语言或某些类似内容的黑客,因为我的首要任务是以我想要的方式获取DLL的公共API,无论任何凌乱的黑客可能隐藏在它的源头内。
所以这是我能提出的最佳解决方案。我自己实际上并没有这样做(现在我不需要为课程使用不同的名字),但我没有任何理由怀疑它不会起作用:
在包含C#类库项目的解决方案中,添加一个新的VB类库项目。
在VB项目中,创建我的原始示例中的类(Value
)。在VB中,添加与类同名的属性没有问题。
如果您的VB类具有需要由C#代码引用的内部方法,请在VB类中使用InternalsVisibleTo
引用C#程序集。
您现在应该能够从C#项目中引用您的VB类。但是当你构建解决方案时,你会得到两个独立的DLL:一个用于C#代码,另一个用于VB代码。看起来ILMerge工具可以非常简单地将两个DLL合并为一个(只需从命令行调用一次)。
所以最后你应该有一个DLL,它包含具有相同名称属性的类,以及C#项目中的所有代码。使用该DLL(C#,VB或任何其他.Net语言)的其他项目不应该看到你的hacky努力 - 所有他们将看到的是一个连贯的API,没有多余的公共类或接口。