9

I'm using C# to make a .Net class library (a DLL) that will be distributed widely. I have an abstract class called Value, and I want it to have an abstract double property that is also called Value i.e.

public abstract class Value {

    // Only accessible by subclasses within the project.
    internal Value() {}

    public abstract double Value {
        get;
    }

}

But the C# compiler won't allow this - I get the message "member names cannot be the same as their enclosing type", as discussed here.

I understand that the easiest thing to do would be to change the name of the property or the name of the class... But really I want the names to be like that, and I'm quite happy to implement an ugly hack to get it that way. So long as it works properly from external code that uses this DLL.

Unlike C#, VB.Net will allow me to define a property with the same name as the class, so I'm currently investigating merging my C# project with a VB project that defines the Value class (and its Value property) to make one DLL. This doesn't seem to be quite as straightforward as I was hoping.

Another option would be to re-write the whole project in VB... Not very appealing, but I'll consider it if necessary. I prefer C# over VB.Net but my priority is to get the built DLL the way I want it.

I'm wondering what other alternatives there might be. Any ideas for a good way to hack this?

EDIT: From the comments below it's clear that quite a number of people don't think much of the name "Value" for a class... Could anyone explain why it's so bad? I know it's not very descriptive, but I think it fits well in the context of my project. Is it because it's a keyword in C# that's used in property setters?

Community
  • 1
  • 1
MB.
  • 7,365
  • 6
  • 42
  • 42
  • 21
    Regardless of the other concerns, `Value` is a very poor name for a class – Marc Gravell Oct 22 '11 at 14:42
  • 4
    Also, if it will "be distributed widely", then observing standard practices is essential, as is good naming. This demonstrates neither. I'd be far more worried about those two concerns than the subtlety of your personal preferences for how you want it to be. – Marc Gravell Oct 22 '11 at 14:47
  • Do not do something like that, it's a really bad design. You are trying to shot yourself and your users in the foot. In brief, in the derived classes, "Value" could be a class or a property... and in the property you even have a "value" parameter. – PRouleau Oct 22 '11 at 14:50
  • That's a fair point. But I think the name Value makes sense in the context of the project. The Value class is basically just a double value with a little metadata as well. It's the superclass of another type called DatedValue which adds some date information, describing a Value for a period between two dates. The whole DLL exists to fetch and use large numbers of these Values from an API, so I think it's good to keep the name short and simple. Then again, if I could think of a good alternative name, that would obviate this issue. – MB. Oct 22 '11 at 14:52
  • Instead of `Value` you could consider using `Datum`: http://dictionary.reference.com/browse/datum – Paul Sasik Oct 22 '11 at 15:44
  • 2
    Thanks for the suggestion Paul. To anyone reading, could you explain the problem with calling a class Value? Is it because it's a very generic term (not descriptive), or is it because it's a word that is used inside property setters? Nullable has a Value property, so I'm assuming that calling the property "Value" is OK (and my Value class, and everything that extends it, is immutable so there is no setter on the property). – MB. Oct 22 '11 at 15:59
  • 4
    I think the problem that everyone is reacting to is that the term Value is so widely used. In designing an API you should aim to keep terms and naming clear and per my suggestion, distinct. Since Value is so prevalent in the .NET framework you risk collision in code and confusion for your customers. – Paul Sasik Oct 22 '11 at 16:31
  • Thanks for the explanation. I am wondering about "Datum". It sounds a little too academic for my liking, but I can see advantages in it. – MB. Oct 22 '11 at 16:57
  • 2
    You know you're doing it wrong when the first words are "what hack can I use..." :) – jb. Oct 22 '11 at 18:14
  • Haha, yes, good point :D If it was a .Net no no I wouldn't even try - it's the fact that it's OK in VB that makes me think it's acceptable if (in my opinion) it makes for a nicer API at the end of the day. – MB. Oct 22 '11 at 18:17
  • Can any question that starts with "What hack can I use ..." be a "good" question? I wouldn't have thought so. But, it has generated some excellent answers and discussion. +1 for the question and several of the answers. – wageoghe Oct 22 '11 at 19:00
  • `Value` isn't at all descriptive of what *it* is. –  Oct 24 '11 at 09:32
  • I have the same question. And I'm frustrated by all the comments that focus on the use of 'value'. It's a fine name ... but more importantly your question is about naming a member the same as the outer class. Who cares what name we talk about! I think it's ridiculous that C# does not support this. If VB can do ... enough said! It's not confusing (to me). It's a useful construct. – steve Nov 10 '14 at 21:53

5 Answers5

8

You cannot do that directly. You could, however, consider:

  • impelenting an interface with a Value member, and using explicit interface implementation (callers would have the use the interface, though)
  • renaming it in the class, and using an extension method to expose a Value() method, so obj.Value() works
  • rename it in the class, but expose it as Value in the subclasses

Ugly hack:

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; } }
}
Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900
  • Thanks for the suggestions. I'm trying to avoid interfaces for compatibility reasons, as I want to be able to add new methods/properties into Value without risking breaking the code of anyone who's implemented the interface themselves. Unfortunately I can't use extension methods because I'm aiming for .Net 2.0 compatibility. The third option would work great if only I could make ValueBase internal (which the compiler doesn't seem to allow). Otherwise I'm messing up the API with an unneeded class. (Well, unneeded as far as anyone using the library is concerned.) – MB. Oct 22 '11 at 14:57
  • @MB indeed the base-class cannot be more-private (that is the 4th option, btw) – Marc Gravell Oct 22 '11 at 14:59
  • "I'm trying to avoid interfaces for compatibility reasons" - This is counter-intuitive. If other people don't want to implement the interface, they can just throw a NotImplementedException. – cwharris Oct 22 '11 at 17:39
  • 2
    No, it's for people that do want to implement the interface, for some bizarre reason. If they implement the interface (even though I don't want them to), I can't ever add another method to the interface without breaking their code. To quote "Framework Design Guidelines", page 88: "The main drawback of interfaces is that they are much less flexible than classes when it comes to allowing for evolution of APIs. After you ship an interface, the set of its members is fixed forever... A class offers much more flexibility..." – MB. Oct 22 '11 at 18:00
3

If your class is representative of a double (except for some additional metadata), you could opt for a conversion operator:

public abstract class Value
{
    protected abstract double GetValue();

    public static explicit operator double (Value value)
    {
        return value.GetValue();
    }
}

Then your client code could access the metadata or cast an instance of type Value to a double. Depending on the metadata and usage, you might make the conversion implicit so you don't have to do an explicit cast, and you might define a conversion from double to Value.

There is a similar approach used by the System.Xml.Linq assembly where, for example, XElement can be cast to any primitive type as a means of accessing its "value".

Michael Petito
  • 12,891
  • 4
  • 40
  • 54
  • That could work... Great idea, thanks :) I shall play about with this. I must confess I'm pretty new to C# and .Net (I've mostly done Java before) so there's a lot that I don't know. – MB. Oct 22 '11 at 17:27
  • 1
    @MB: No problem, as an FYI, here are some design guidelines for conversion operators: http://msdn.microsoft.com/en-us/library/ms229033.aspx – Michael Petito Oct 22 '11 at 17:30
2

As other people have said, this is not possible in C#.

Other people have criticised the name Value as a class, and while I agree it's likely too generic, I can see situations where it may make sense.

Bearing that in mind, if Value is an abstract class, perhaps ValueBase might be a decent, conformant, name? Much of the .Net framework (particularly WPF) uses XxxBase.

Another option to consider is prefixing the class name with the name of your project, as in FooValue.

Grokys
  • 16,228
  • 14
  • 69
  • 101
  • Thanks Groky. I'm considering going with ValueBase. It's not ideal though, as, although Value is an abstract class, all its concrete implementations are internal apart from DatedValue. Value has a static factory method that creates instances of a couple of internal types that are only exposed as Value. It's a little complicated internally, but I think it makes for a nice, usable API in the context. Other public objects in the library have properties and methods like AnnualAverage and MonthlyAverage(month) which all return Value objects. – MB. Oct 22 '11 at 16:53
  • 1
    @MB.: another option to consider is prefixing it with the name of you project, as in FooValue. – Grokys Oct 22 '11 at 16:56
  • Actually I'll add that to my answer ;) – Grokys Oct 22 '11 at 16:57
  • Something like that could potentially work... Good suggestion. Though the name would be a little on the long side. I'm still tempted to re-write what I've done so far in VB just so I can call the class and the property "Value" alone. – MB. Oct 22 '11 at 17:01
  • @MB.: I've actually encountered a similar situation where I needed a base class that was so general that the only name I could think of was "Object". For this I prepended the project name. If it's too long, then maybe an acronym? – Grokys Oct 22 '11 at 17:04
  • Yeah I've been wondering about that too... Honestly you wouldn't believe how much thought I've put into the naming of classes and methods on this project. It's verging on ridiculous. Reminds me of the saying: "There are 2 hard problems in computer science: caching, naming, and off-by-1 errors"! – MB. Oct 22 '11 at 17:09
2

Value is a terrible name for a class. It's extremely vague, so it does nothing to describe what a Value represents, and it clashes with the reserved word 'value'. You will find yourself using value = Value.Value, wondering why your code makes no sense, and eventually trying to fix a hideous bug that is a direct result of using 'value' instead of Value or value or _value or this.value. And what happens when you have to store another kind of arbitrary number? Will you call it Value2?

Name the class with a more specific and meaningful name and the problem will no longer exist. Don't fix the symptoms - fix the cause.

Even if you only rename it to "DataValue" or 'MySystemValue', you will be doing yourself a great service.

Jason Williams
  • 56,972
  • 11
  • 108
  • 137
2

Bowing to popular opinion, I've decided to rename my Value class to DataValue. I'm pretty happy with that name, and it means I don't need any hacks to have the property called Value. So thank you very much to everyone for the feedback.

But, despite the useful answers, I still don't think the question has been answered ideally. None of the proposed solutions do exactly what was asked for, or at least not without side effects like the requirement for an otherwise-superfluous interface or public class. I should probably have been clearer in my question that I was perfectly happy to consider a hack that involved unsafe code, or modification of intermediate language or some such, as my priority was to get the public API of the DLL the way I wanted it, irrespective of whatever messy hacks might lurk hidden within it's source.

So here's the best solution that I could come up with. I haven't actually done it myself (no need now I'm using a different name for the class), but I don't have any reason to suspect that it won't work:

  1. In the solution that contains your C# class-library project, add a new VB class-library project.

  2. In the VB project, create the class (Value in my original example). In VB you'll have no problems adding a property with the same name as the class.

  3. If your VB class has internal methods that need to be referenced by your C# code, reference the C# assembly using InternalsVisibleTo in your VB class.

  4. You should now be able to reference your VB class from your C# project. But when you build the solution you'll get two separate DLLs: one for the C# code and one for the VB code. It looks like the ILMerge tool makes it very straightforward to merge the two DLLs into one (just one call from the command line).

So finally you should have a single DLL that contains the class with the property of the same name, and all the code in your C# project. Other projects that use that DLL (C#, VB, or any other .Net language) should not see your hacky effort - all they'll see is a coherent API with no superfluous public classes or interfaces.

MB.
  • 7,365
  • 6
  • 42
  • 42