1

I would like to make the cert variable below to be a const? When I do that, I get an error, "The expression being assigned to cert must be a constant". I have seen articles online asking to convert it to static readonly as opposed to const, and also saying that to be a const, the value should be known at compile time.

I have two questions

  1. Is it not possible for cert to be a const variable, since I do not want it to be modified?
  2. I tried making the cert variable a readonly, and that too gives me an error, "The modifier readonly is not valid for this item".

Program.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace IAMAGoodDeveloper
{
    public static class Program
    {
        static void Main(string[] args)
        {
            programStart();
        }

        private static void programStart()
        {
            var myFactory = new MyFactory();
            var secretsProvider = myFactory.GenerateKeyProvider();
            const int cert = secretsProvider.GetKey("arg");
        }
    }
}

MyFactory.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace IAMAGoodDeveloper
{
    public class MyFactory
    {
        public KeyGen GenerateKeyProvider()
        {
            return new KeyGen();
        }
    }

    public class KeyGen
    {
        public int GetKey(string arg)
        {
            return 1;
        }
    }
}

4 Answers 4

3

const is compile time keyword that will replace all references to you're const variable with a hard coded value in the compiled code

public class MyClass
{
    private const int MyNumber = 2;

    public void MyMethod()
    {
        Console.WriteLine(MyNumber);
    }
}

When this gets compiled the resulting code looks like this

public class MyClass
{


    public void MyMethod()
    {
        Console.WriteLine(2);
    }
}

It will have been compiled to IL but you get the point.

This means that you can only mark things as constant that are known at compile and are C# primitive objects, like string, int, decimal etc.

readonly is currently not allowed for variables unfortunately. However there is talk of making it possible https://www.infoq.com/news/2017/04/CSharp-Readonly-Locals

1

You cannot use const with instantiated objects. A good alternative would be a static readonly field at class-level though.

1
  • Like this you mean, public static class Program { static MyFactory myFactory = new MyFactory(); static KeyGen secretsProvider = myFactory.GenerateKeyProvider(); static readonly int cert = secretsProvider.GetKey("arg"); static void Main(string[] args) { programStart(); } private static void programStart() { Console.WriteLine(cert); Console.ReadLine(); } } That works. Commented Oct 6, 2018 at 0:57
1
  1. You can not use const. You can think of const less like a variable, and more like a macro that replaces all instances with the value at compile time. It can only be used with strings and primitives.

  2. You can only use readonly with fields, not with local variables. Maybe that should be allowed, but it is not.

1
  • 1
    I explain it by saying "Think of a const as a symbolic alias for a literal". If you can't use a literal, you can't use a const
    – Flydog57
    Commented Oct 6, 2018 at 4:11
0

When I do that, I get an error, "The expression being assigned to cert must be a constant".

Ignoring what you want, and looking at the limitations of what c# provides for const values: const (C# Reference).

Constants can be numbers, Boolean values, strings, or a null reference.

I don't know what else to tell you, you simply can't use an instantiated object.

Now an alternate way to create a somewhat safe readonly object is to only expose an interface:

public class MyFactory
{
    public IKeyGen GenerateKeyProvider()
    {
        return new KeyGen();
    }

    public interface IKeyGen 
    {
      int GetKey(string arg);
    }

    private class KeyGen : IKeyGen
    {
        public int GetKey(string arg)
        {
            return 1;
        }
    }
}

Since you've not included any usage of this object, it's extremely hard to determine anything other than you don't want the object itself to change.

Not the answer you're looking for? Browse other questions tagged or ask your own question.