-5

In Delphi you can declare a constant in a method and assign it a value in that same method. The idea is that next time you are in this method, the const will still have the same value that you last assigned it.

It looks like this in Delphi :
(I don't have Delphi here so it is untested, sorry about that, but it is enough to demonstrate what I mean)

procedure Form1.test;
const
  AssignableConst: Integer = 0;
begin
  ShowMessage(AssignableConst);
  inc(AssignableConst);
end;

Every time you call the procedure test the messagebox will show the last value + 1

This example is completely useless I know that it is just to show how an assignable const works in Delphi.

Is there an equivalent for this in c# ?
I don't want a solution that involves private variables in the class, it has to stay inside the method.

My question is about scope. Nothing else. I don't care that the value is part of the state of the object. That is not important. What is important is that I need a variable that is only accessible from the scope of a method, nowhere else.
In Delphi this can be done by using an assignable const, so how can I do this in C#?

BoltClock
  • 700,868
  • 160
  • 1,392
  • 1,356
GuidoG
  • 11,359
  • 6
  • 44
  • 79
  • 2
    "I dont want a solution that involves private variables in the class, it has to stay inside the method." why? Hiding persistent state sounds like a dubious idea. – CodesInChaos Dec 15 '16 at 12:23
  • For non-`sealed` classes simply use `private` modifier for the field. It make sense to name it appropriately, e.g. `_testCounter` (where test is method name), then other method can have its own field and you won't mix them by accident. In C# there is no local static variable, so you must use field. Scope doesn't matter, if you really want, then you can try to encapsulate method into separate `class`. – Sinatr Dec 15 '16 at 12:24
  • Because the method is the only scope where this const (or variable if you want) should be readable and writable – GuidoG Dec 15 '16 at 12:24
  • Also should the state be per-instance or global? – CodesInChaos Dec 15 '16 at 12:25
  • @CodesInChaos Since the method is part of a class, it will be per instance of that class. The idea is to have a variable or const that only this method knows, and that does not gets reset everytime that method is called in the same instance of the object the method belongs to – GuidoG Dec 15 '16 at 12:27
  • Just use an instance field. Encapsulation and using small scopes is all nice and great, but at some point you have to trust closely related code not to misbehave. – CodesInChaos Dec 15 '16 at 12:28
  • 1
    Long story short - that would be a nice feature but it's not supported. – Evk Dec 15 '16 at 12:29
  • Technically you could abuse a closure for similar effect (storing the delegate in an instance field and the counter inside the closure), but that doesn't seem better than using an instance field directly here. – CodesInChaos Dec 15 '16 at 12:30
  • I gather from the comments that this feature is not supported by c#. Too bad. So I will have no choice but to use a private field after all. Thanks for all your help – GuidoG Dec 15 '16 at 12:32
  • 2
    Actually your Delphi const is global per application, not the instance class. your example does not uses a class instance. – kobik Dec 15 '16 at 12:32
  • @kobik I edited my question so the prodecure is part of a form – GuidoG Dec 15 '16 at 12:34
  • C# 7 will support a method level variable (even method within method). – Hagay Goshen Dec 15 '16 at 12:36
  • You can do that in Delphi, but its not recommended. Writable consts are considered a depreciated feature now that properties/statics/initialisable globals are available, so much so a compiler switch is required to enable them. – Alex K. Dec 15 '16 at 12:37
  • 2
    a local writable const is global per application even when used in a class instance, and shared among instances. what are you trying to achieve exactly? – kobik Dec 15 '16 at 12:42
  • 1
    @kobik I need in one method a variable that I can assign a value that will survive when the method goes out of scope, and no other medhod should be able to mess with that variable. – GuidoG Dec 15 '16 at 12:44
  • @HagayGoshen: Not sure which C# 7 feature you're talking about. You'll be able to declare methods within methods, but I don't think you'll be able to declare *fields* within methods, which is what this is asking about. – Jon Skeet Dec 15 '16 at 12:46
  • 2
    @CodesInChaos: Delphi's "writable const" is the equivalent of a static local variable in C and C++. Nothing wrong with that. It has the scope of the method, not of the class. That has its advantages, and there is nothing wrong with "hiding" this from the rest of the class. – Rudy Velthuis Dec 15 '16 at 13:25
  • 1
    Why are you editing spelling/grammar mistakes *into* your question? And meta commentary has no place in your question. Your question is where you ask your question, not where you complain about people not doing what you want. – Servy Dec 15 '16 at 14:23
  • @Servy I am sorry but I am just dissapointed that I get people here that dont undestand my question and I got a little mad about it – GuidoG Dec 15 '16 at 14:27
  • Relevant Roslyn proposal: [Please allow to define static local variables in functions, like C/C++ #10552](https://github.com/dotnet/roslyn/issues/10552). Also, that specific usage of assignable `const` in Delphi [is frowned upon](http://stackoverflow.com/q/8463604). Right now, that can't be done in C#. You should really not nitpick about the scope of **private** static fields, it's **your** code after all. Any .NET language compiler will have to generate one in IL, or something that can be made to behave like it (*coff* a static concurrent dictionary with very weird keys *coff*). – acelent Dec 16 '16 at 00:34
  • @acelent Thanks for your input. I already said in one of the comments that I understand it is not possible in c# and will use the private field solution. For the nitpicking about the scope, well my question is about scope... – GuidoG Dec 16 '16 at 07:46

2 Answers2

10

I don't want a solution that involves private variables in the class, it has to stay inside the method.

But the value is part of the state of the object (or type, for a static method) - so it makes sense for it to be a field declared in the object.

There's no equivalent to this in C#. The best you can do is have a private variable and document that it should only be used from a specific method. (You could write Roslyn-based tests for that if you really want.)

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • No it does not makes sense to have it a private field in the object. The method is the only scope where this const should be readable and writable – GuidoG Dec 15 '16 at 12:24
  • 5
    Then maybe you should extract the method in it's separate class – Zsolt Z. Dec 15 '16 at 12:36
  • @GuidoG: But it *is* part of the state of the object, isn't it? As Zsolt says, you could create a separate class and put the method there, then have a field of that new class within your original object... – Jon Skeet Dec 15 '16 at 12:38
  • @ZsoltZ. you are missing the point. This answer is useless since it does not provide a solution to the question, only a workaround which was mentioned in the question that I did not wanted that workaround. Putting the method in its own class would mean passing it tons of variables – GuidoG Dec 15 '16 at 12:39
  • 1
    @GuidoG: It answers the question of "Is there an equivalent for this in c#?" - the answer to that is no. It explains *why* there isn't, and why the "workaround" is entirely reasonable. You haven't explained anything about why you think the declaration has to be in the method. – Jon Skeet Dec 15 '16 at 12:39
  • @JonSkeet It does not matter if it is part of the state of the object, you are missing the point – GuidoG Dec 15 '16 at 12:40
  • @GuidoG: Well, I think you're missing *my* point: the state of an object is declared in its fields. This is part of the state of the object, therefore it is declared in its fields. In other words, you're asking for something that goes against the philosophy of the language. Maybe if you'd given some *reason* why you want to declare object state in a method (which normally only declares state for that invocation) it would be clearer, but personally I'm glad this feature *doesn't* exist. – Jon Skeet Dec 15 '16 at 12:41
  • @JonSkeet Yes your answer does indeed gives an alternative you are right. The reason why I want this is simple, prevent any other method in that class from messing with that variable – GuidoG Dec 15 '16 at 12:43
  • @GuidoG: And I answered that part as well: if you really don't trust other code within the same class declaration, you can add a test. But if you don't trust the coders working on this class, what makes you think they wouldn't just move the declaration out of the method anyway? Basically, within the program text of a class, there's maximal trust. Yes, you can make variables `readonly` for example, but you can't limit visibility of state. – Jon Skeet Dec 15 '16 at 12:44
  • @JonSkeet do you agree that it might be a useful feature if implemented? Or you claim that it's not needed because you can always use field instead? – Evk Dec 15 '16 at 13:03
  • I gather from the comments that this feature is not supported by c#. Too bad. So I will have no choice but to use a private field after all. Thanks for all your help. – GuidoG Dec 15 '16 at 13:04
  • 1
    @JonSkeet: it is actually part of the state of the class. But like static local variables in, say C++, it is not (inadvertently) accessible and therefore not (inadvertently) modfiiale outside that one specific method. So its integrity can be maintained inside that method and only that code has to be maintained if something changes. – Rudy Velthuis Dec 15 '16 at 13:33
  • @Rudy: The OP may be confused about what they want then... But the general point remains, that the state of the type is in static fields. – Jon Skeet Dec 15 '16 at 13:36
  • No I am not confused about it, I said from the very beginning I want a variable that is only accesable from inside that method and can survive when the method is going out of scope – GuidoG Dec 15 '16 at 13:42
  • @GuidoG: my point is that you said you want per-instance state, and Rudy suggests it's per-class state. That's where there may be confusion - but either is easily achieved using a field. – Jon Skeet Dec 15 '16 at 13:44
  • I dont want per instance state, I dont care about that. I said that since the method is part of a class it wiill also be per instance. But that is not important and does not matters at all. The point is that this variable should only be visible in the scope of that method. I dont care about the instance state and only answered that because you asked it – GuidoG Dec 15 '16 at 13:46
  • 2
    @GuidoG: The difference between per instance state and per type state is *very* important. Your answer to CodesInChaos's question was really pretty clear - if you didn't want per instance state, you should'nt have said "and that does not gets reset everytime that method is called in the same instance of the object the method belongs to". *You* may not care about the distinction, but the point of Stack Overflow is to create a repository of high quality questions and answers - you do a disservice to future readers if you say your original code does one thing when actually it does something else. – Jon Skeet Dec 15 '16 at 14:09
  • where do I say it wants one thing and it actually does someting else ???? – GuidoG Dec 15 '16 at 14:13
  • 2
    @GuidoG: Your fifth comment on the question states that you want per instance state. You later say (two comments above this) that you *don't* want per instance state. Fundamentally, you seem to be entirely about getting an answer to your very specific requirement without thinking about future readers of the question. You've already received the answer: "You can't do this in C#." I don't think there's anything more to be said, really. – Jon Skeet Dec 15 '16 at 14:15
  • I only said that because you kept asking that. I dont care about it, i care about scope, Nothing else but scope. Is that so hard to understand ? – GuidoG Dec 15 '16 at 14:17
  • 3
    @GuidoG: I'm done. You're being rude, ignoring the purpose of the site, and ignoring the fact that you've already got an answer to your question. – Jon Skeet Dec 15 '16 at 14:18
1

The closest you can get is:

class MyClass
{
    static Action CreateCounter()
    {
        int counter = 0;
        return () => {
            Show(counter);
            counter++;
        };
    }

    Action showAndIncrementCounter = CreateCounter();

    public ShowAndIncrementCounter()
    {
        showAndIncrementCounter();
    }
}

But I still recommend the simple solution of using an instance field for the counter and just not accessing it from outside the method.

CodesInChaos
  • 106,488
  • 23
  • 218
  • 262
  • In my example I always increased the value with 1 That was just an example in my application I have to be able to assign it any value at all inside the method. – GuidoG Dec 15 '16 at 12:36
  • 1
    @GuidoG So? You can change my example in exactly the same way you change your example. – CodesInChaos Dec 15 '16 at 12:37
  • Yes I see now, but I agree that using an instance field would be a better workaround for my problem – GuidoG Dec 15 '16 at 12:47