class foo {
public readonly int bar;
};
foo a = new foo() { bar = 123 };
error CS0191: A readonly field cannot be assigned to (except in a constructor or a variable initializer)
How can I assign bar in the object initializer above?
Can I initialize readonly members without having to write a custom constructor for every class/struct ?
To summarize the sentiment of the other answers: The error message isn't helpful— object initializers can't be used with readonly fields.
However, constructors with named arguments can, and the syntax to do so is quite similar. So similar you might even be thinking that you've seen C# object initializers for readonly fields (like I have been) when what you actually saw was this:
class Foo {
public Foo(int bar) {
this.bar = bar;
}
public readonly int bar;
};
Foo a = new Foo(bar: 123);
// instead of `new Foo() { bar = 123 };`
foo a = new foo() { bar = 123 };
is transformed by the compiler to
foo temp = new foo();
temp.bar = 123;
foo a = temp;
As you can see, the assignment to bar is neither in the foo constructor nor a variable initializer.
So the answer is: you can't.
You pass the value in on the constructor:
public class foo
{
public readonly int _bar;
public foo(int bar)
{
_bar = bar;
}
};
var x = new foo(12345);
What the compiler is telling you is that the only place you can set your readonly field is in the constructor of the class that holds it, this means:
if you need it to change during the lifetime of the object then readonly is not the correct option to use
if each instance of the class needs to hold a custom value in the readonly member variable then you need to inject it as part of the constructor
I would suggest that it isn't a good practice to make your readonly field public like this, instead just expose it as a public property that only has a getter.
class Foo {
private int bar;
public Foo( int bar ){
this.bar = bar;
}
public int Bar {
get { return this.bar; }
}
}
Foo foo = new Foo( 123 );
You can't. You should use the constructor for it.
MSDN
You can't. What the error wants to tell you that you could use
class foo {
public readonly int bar = blabla;
};
The object initializer syntax you're using is just syntax sugar for calling the constructor and the assigning to members. And that' not allowed for readonly members.
You will need to introduce a constructor parameter, and then assign in the constructor. C# is pretty lacking concerning syntax sugar for immutable types.
Related
This should sound like a really basic question, but I haven't been able to find an answer (even tho I know for sure there are plenty), I guess my Googling skills are bad, or maybe I don't know what to search for.
I have this code:
using System;
public class Program
{
public static void Main()
{
var service = new Service();
service.Execute();
}
}
public class Service
{
private int _foo;
public void Execute()
{
_foo = 1;
var bar = new Bar(_foo);
_foo = 2;
bar.WriteLine();
}
}
public class Bar
{
private readonly int _foo;
public Bar(int foo)
{
_foo = foo;
}
public void WriteLine()
{
Console.WriteLine(_foo);
}
}
How can I make it so it prints 2? (basically the new value after Bar has been initialized)
I tried using ref but no luck.
What you are trying to do doesn't make sense for a value type
Value types and reference types are the two main categories of C#
types. A variable of a value type contains an instance of the type.
This differs from a variable of a reference type, which contains a
reference to an instance of the type. By default, on assignment,
passing an argument to a method, or returning a method result,
variable values are copied. In the case of value-type variables, the
corresponding type instances are copied.
Normally you would create this as a property and set it accordingly
Given
public class Bar
{
public Bar(int foo) => Foo = foo;
public int Foo {get;set;}
public void WriteLine() => Console.WriteLine(Foo);
...
Usage
public void Execute()
{
var bar = new Bar(1);
// set the property instead
bar.Foo = 2;
bar.WriteLine();
...
Are there any differences between the following two approaches (property with backing field and property with default value) for a lazily evaluated property or are they equivalent?
// (1)
public static class Foo
{
private static readonly Lazy<Foo> instance = new Lazy<Foo>();
public static Foo Instance { get; } = instance.Value;
}
// (2)
public static class Foo
{
public static Foo Instance { get; } = new Lazy<Foo>().Value;
}
What I want to achieve is that an instance of Foo is created only when accessing Foo.Instance, not before --- more so, when Foo.Instance is never accessed, no instance should be created ever.
Well, actually, no, they're not different.
But, and this is just an assumption mind you, they're not working either, at least not the way I hope you intended them do.
You see, this syntax:
<property declaration> = <expression>;
Declares an initializer for the property, which will be executed on construction of the owning type.
So this:
private static readonly Lazy<Foo> instance = new Lazy<Foo>();
public static Foo Instance { get; } = instance.Value;
is not lazy at all. It will declare and construct a Lazy<Foo> (although you're probably missing the getter delegate here as well even though this compiles), however when you declare the property you end up with the property evaluating the lazy object upon construction of the owning type and thus it becomes non-lazy.
The second one has the exact same problem, you construct and immediately evaluate the lazy object so it becomes non-lazy.
The correct way, and this can only be achieved in sort of the first syntax form, is to use the property without an initializer, either this:
private static readonly Lazy<Foo> instance = new Lazy<Foo>();
public static Foo Instance
{
get { return instance.Value; }
}
or this:
private static readonly Lazy<Foo> instance = new Lazy<Foo>();
public static Foo Instance
{
get => instance.Value;
}
or probably best, as this:
private static readonly Lazy<Foo> instance = new Lazy<Foo>();
public static Foo Instance => instance.Value;
This will declare a getter body that doesn't execute until you actually read the property.
TL;DR To sum it up, the two examples you gave are not different, but they're both (probably) wrong and you need to change the property declaration to fix it.
Apart from the excellent answer given by Lasse Vågsæther Karlsen, I would like to further speculate and assume that OP is after Singleton implementation. Here is a fully lazy approach.
Approach 1
public sealed class Singleton {
//Private ctor of course :P
private Singleton() {}
// Instance property to access Singleton Instance
public static Singleton Instance { get { return Nested.instance; } }
private class Nested {
// Explicit static constructor to tell C# compiler
// not to mark type as beforefieldinit
static Nested() { }
internal static readonly Singleton instance = new Singleton();
}
}
Approach 2
public sealed class Singleton
{
private static readonly Lazy<Singleton> lazy =
new Lazy<Singleton>(() => new Singleton());
public static Singleton Instance { get { return lazy.Value; } }
private Singleton()
{
}
}
I'm confused about this statement:
ctrlID.Font.Size = FontUnit.Small;
but FontUnit is a struct under System.Web.UI.WebControls
public struct FontUnit
{
...
public static readonly FontUnit Small;
...
}
as a struct is a class, so how can we have a class A that has its self as a object like:
public class A{
public A a;
}
isn't it like creating an endless chain of objects which would require infinite memory?
The property is static, so it's a member of the Type, and not of the object instance. You do not need to construct the Small static property to create a FontUnit object.
Consider this:
public class Foo
{
public static Foo Default {get;}
static Foo()
{
Default = new Foo();
}
}
Default is only constructed once, at an unknown time before it is used.
If it's not static, you can get into the behavior you expected.
public class Foo
{
public Foo Default {get; private set;}
public Foo()
{
Default = new Foo();
}
}
This will cause an overflow, as the property will keep instantiating a new Foo, which will make a new Foo, and so on.
So long as you're careful not to instantiate a type with the same constructor you are currently instantiating a type in there shouldn't be any issue with a type having member of it's own type.
When I was in university 6-8 years ago, I learned that it was common practise to have public get and set methods but private variables when using Java. However these days, when I use C#, I realise that a lot of the common class variables have public accessibility, e.g. String.Length.
Is it common practise in C# to make variables public (so is it widely accepted that people can program in such a manner)?
Thanks
String.Length isn't really a public variable. In C#, it's common to use getters this way:
class Foo
{
private int _bar;
public int Bar
{
get { return _bar; } // getter
set { _bar = value; } // setter
}
}
// ...
Foo foo = new Foo();
foo.Bar = 42;
In other words, string.Length is only a getter for the read only variable string._lengh.
Often, it's also a good practice to mark the setter as private meaning that only the where your setter is declared can set the value for your property, and any other derived class can access it with the getter method.
So there are a couple of ways to declare properties with:
Use the prop shortcut and hit Tab twice (Code Snippets in Visual Studio). This produces:
public int Foo{ get; set; }
Use the propg shortcut + Tab twice to declare the setter as private. Looks like this:
public int Foo{ get; private set; }
Use the full implementation in using the shortcut propfull which will give you:
private int Foo;
public int MyProperty
{
get { return Foo;}
set { Foo = value;}
}
You can also make a public variable readonly, instead of making its setter private:
class Foo
{
public readonly int Bar; // Bar can only be initialized in the constructor
public Foo()
{
this.Bar = 42;
}
}
As far as I know you can can't pass parameters to a static constructor in C#.
However I do have 2 parameters I need to pass and assign them to static fields before I create an instance of a class. How do I go about it?
This may be a call for ... a Factory Method!
class Foo
{
private int bar;
private static Foo _foo;
private Foo() {}
static Foo Create(int initialBar)
{
_foo = new Foo();
_foo.bar = initialBar;
return _foo;
}
private int quux;
public void Fn1() {}
}
You may want to put a check that 'bar' is already initialized (or not) as appropriate.
You can't pass parameters to a static constructor, but you can pass parameters to the class itself - via generic type parameters.
Slightly crazy this idea, however, I'll just throw it out there anyway.
Make the class generic (with a TypeParam that will provide a parameter type) and place generic constraints on it (details in code example), then derive a new parameter type, which contains virtuals that you can use to read what they want the parameter values to be.
//base parameter type - provides the 'anchor' for our generic constraint later,
//as well as a nice, strong-typed access to our param values.
public class StaticParameterBase
{
public abstract string ParameterString{ get; }
public abstract MyComplexType ParameterComplex { get; }
}
//note the use of the new() generic constraint so we know we can confidently create
//an instance of the type.
public class MyType<TParameter> where TParameter:StaticParameterBase, new()
{
//local copies of parameter values. Could also simply cache an instance of
//TParameter and wrap around that.
private static string ParameterString { get; set; }
private static MyComplexType ParameterComplex { get; set; }
static MyType()
{
var myParams = new TParameter();
ParameterString = myParams.ParameterString;
ParameterComplex = myParams.ParameterComplex;
}
}
//e.g, a parameter type could be like this:
public class MyCustomParameterType : StaticParameterBase
{
public override string ParameterString { get { return "Hello crazy world!"; } }
public override MyComplexType { get {
//or wherever this object would actually be obtained from.
return new MyComplexType() { /*initializers etc */ };
}
}
}
//you can also now derive from MyType<>, specialising for your desired parameter type
//so you can hide the generic bit in the future (there will be limits to this one's
//usefulness - especially if new constructors are added to MyType<>, as they will
//have to be mirrored on this type as well).
public class MyType2 : MyType<MyCustomParameterType> { }
//then you'd use the type like this:
public static void main()
{
var instance = new MyType<MyCustomParameterType>();
//or this:
var instance2 = new MyType2();
}
I did consider a solution that employs custom type attributes applies to a type parameter, however this is easily a better way. However, you'll now be using your class always with a generic parameter type (unless you can use the deriving+specialisation trick) - possibly too clumsy for your liking.
I'd also prefer this over the other solutions presented here as it doesn't require creating any workarounds for the static initialisation - you can still use .Net's guarantee of single-time initialisation.
A word of warning - should you be reviewing your structure?
All that said - remember, though, since you can only parameterise the static once (or in this case, each uniquely parameterised static generic) - I would be asking myself why not just pull the code that is getting the parameters to give to the static, and place it in the static constructor in the first place? That way you don't actually have to resort to strange patterns like this!
I assume you mean static members of a class? In that case, you can do this:
public class MyClass
{
public static int MyInt = 12;
public static MyOtherClass MyOther = new MyOtherClass();
}
Those static members are guaranteed to be instantiated before any class is instantiated.
If you need complex logic, do it in a static constructor:
public class MyClass
{
public static int MyInt;
public static MyOtherClass MyOther;
static MyClass()
{
MyInt = 12;
MyOther = new MyOtherClass();
}
}
Edit
Based on your edit, I'd say just assign the values to what they need to be before you instantiate the class, like so:
public class MyClass
{
public static int MyInt;
public static MyOtherClass MyOther;
}
// elsewhere in code, before you instantiate MyClass:
MyClass.MyInt = 12;
MyClass.MyOther = new MyOtherClass();
MyClass myClass = new MyClass();
That said, this method gives you no guarantee that MyInt and MyOther are set before MyClass is instantiated. It will work, but requires discipline before instantiating MyClass.
One alternative pattern you might follow looks like this:
public class MyClass
{
private static int MyInt;
private static MyOtherClass MyOther;
private static bool IsStaticInitialized = false;
public static InitializeStatic(int myInt, MyOtherClass other)
{
MyInt = myInt;
MyOther = other;
IsStaticInitialized = true;
}
public MyClass()
{
if(!IsStaticInitialized)
{
throw new InvalidOperationException("Static Not Initialized");
}
// other constructor logic here.
}
}
// elsewhere in your code:
MyClass.InitializeStatic(12, new MyOtherClass());
MyClass myClass = new MyClass();
// alternatiavely:
MyClass myClass = new MyClass(); // runtime exception.