I've been looking for a decent definition of static arrays. I've tried using msdn and c# sources but cannot seem to find a definition. It gives examples, but no definitions...
Does anyone know any links or definitions and characteristics of a static array please?
When you talk about a 'static array' you are really talking about two separate things.
One would be the static keyword. When applied to variables this means that the variable lives at the class level, and each object of that type will not get its own instance.
An array is simply a data structure for holding multiple values of some type.
So, a static array is simply an array at the class level that can hold multiple of some data type.
For example:
In your TravelRoute class, you may have a set number of possible destinations in a route. These could be defined like so:
class TravelRoute {
public static Destination[] possibleDestinations =
new Destination[]{
new Destination("New York"),
new Destination("Minneapolis"),
new Destination("NParis")
};
}
This will define the possible destinations on a TravelRoute. You can then access the array like so:
Destination one = TravelRoute.possibleDestinations[0];
Do you possibly mean fixed size arrays?
unsafe struct Foo
{
fixed int Values[8];
}
If so, you will get more search results by using fixed size arrays as your query :)
There's nothing (that I know of) that's special about static arrays, per se, which may be why you're having trouble finding good write-ups about them. Correct me if I'm wrong, but I wonder if it's the "static" part that you're most interested in? Basically, static means that the member exists at the class level rather than the instance level, so a static array would be an array that belongs to the class (rather than an instance of the class).
Example:
public class Foo
{
public static int[] Numbers {get; set;}
}
public class Bar
{
public int[] Numbers {get;set;}
}
public class Program
{
public void Main()
{
// NOTE: Foo itself has this array
Foo.Numbers = new int[]{1,2,3};
// NOTE: it's this particular instance of a Bar that has this array
Bar bar = new Bar();
bar.Numbers = new int[]{1,2,3};
}
}
Related
I have a question about creating an immutable struct inside a class definition. I want to define the struct outside the class but use that same struct type in the class definition while maintaining immutability. Will the code below achieve this?
namespace space
{
class Class1
{
public Struct {get; set;}
}
public Struct
{
public Struct(string strVar)
{
StructVar = strVar;
}
public string StructVar {get;}
}
}
Also, if I have a struct within a struct like:
class Class1
{
public Struct2 {get; set;}
}
public struct Struct2
{
public Struct2(string str, InStruct inStrct)
{
StrVar = str;
InStruct = inStrct;
}
public string StrVar {get;}
public InStruct InStruct {get;}
}
public struct InStruct
{
public InStruct(Array ary)
{
StrArray = ary
}
public Array StrArray {get;}
}
Does this also maintain immutability?
Lastly, if the size of the array in the InStruct is likely to be quite long, should I not use a struct at all and just put the array itself into the class definition instead? Am I just going struct crazy?
My concern is that because I'm doing a {set;} in the class definition that I'm breaking a rule somewhere. I would put the struct in the class definition itself but I didn't like to have to continuously call class constructors over and over to create each struct, that kind of seemed to defeat the purpose of using a struct in the first place.
It's a little difficult to give a complete answer without understanding exactly what you are trying to accomplish, but I'll start with a few important distinctions.
First, in C#, the struct/class distinction isn't about mutability per se. You can have a immutable class, like this one
public class CannotBeMutated
{
private string someVal;
public CannotBeMutated(string someVal)
{
_someVal = someVal
}
public string SomeVal => _someVal;
}
and a mutable struct, like this one
// This is not at all idiomatic C#, please don't use this as an example
public struct MutableStruct
{
private string _someVal;
public MutableStruct(string someVal)
{
_someVal = someVal;
}
public void GetVal()
{
return _someVal
}
public void Mutate(string newVal)
{
_someVal = newVal;
}
}
Using the above struct I can do this
var foo = new MutableStruct("Hello");
foo.mutate("GoodBye");
var bar = foo.GetVal(); // bar == "GoodBye"!
The difference between structs and classes is in variable passing semantics. When an object of a value type (e.g. a struct) is assigned to a variable, passed as a parameter to or returned from a method (including a property getter or setter) a copy of the object is made before it is passed to the new function context. When a object of a reference type is passed as a parameter to or returned from a method, no copy is made, because we only pass a reference to the object's location in memory, rather than a copy of the object.
An additional point on struct 'copying'. Imagine you have a struct with a field that is a reference type, like this
public struct StructWithAReferenceType
{
public List<string> IAmAReferenceType {get; set;}
}
When you pass an instance of this struct into a method, a copy of the reference to the List will be copied, but the underlying data will not. So if you do
public void MessWithYourSruct(StructWithAReferenceType t)
{
t.IAmAReferenceType.Add("HAHA");
}
var s = new StructWithAReferenceType { IAmAReferenceType = new List()};
MessWithYourSruct(s);
s.IAmAReferenceType.Count; // 1!
// or even more unsettling
var s = new StructWithAReferenceType { IAmAReferenceType = new List()};
var t = s; // makes a COPY of s
s.IAmAReferenceType.Add("hi");
t.IAmAReferenceType.Count; // 1!
Even when a struct is copied, its reference type fields still refer to the same objects in memory.
The immutable/mutable and struct/class differences are somewhat similar, insofar as they are both about where and whether you can change the contents of an object in your program, but they are still very distinct.
Now on to your question. In your second example, Class1 is not immutable, as you can mutate the value of Struct2 like this
var foo = new Class1();
foo.Struct2 = new Struct2("a", 1);
foo.Struct2 // returns a copy of Struct2("a", 1);
foo.Struct2 = new Struct2("b", 2);
foo.Struct2 // returns a copy of Struct2("b", 2);
Struct2 is immutable, as there is no way for calling code to change the values of StrVar or InVar once. InStruct is similarly immutable. However, Array is not immutable. So InStruct is an immutable container for a mutable value. Similar to if you had a ImmutableList<List<string>>. While you can guarantee calling code does not change the value of InStruct.StrArray to a different array, you can do nothing about calling code changing the value of the objects in the Array.
Finally, some generic advice related to your example.
First, mutable structs, or structs with mutable fields, are bad. The examples above should point to why structs with mutable fields are bad. And Eric Lippert himself has a great example of how terrible mutable structs can be on his blog here
Second, for most developers working in C# there's almost never a reason to create a user defined value type (i.e. a struct). Objects of value types are stored on the stack, which makes memory access to them very fast. Objects of reference types are stored on the heap, and so are slower to access. But in the huge majority of C# programs, that distinction is going to be dwarfed by the time cost of disk I/O, network I/O, reflection in serialization code, or even initialization and manipulation of collections. For ordinary developers who aren't writing performance-critical standard libraries, there's almost no reason to think about the performance implications of the difference. Heck, developers in Java, Python, Ruby, Javascript and many other languages get by in languages totally without user-defined value types. Generally, the added cognitive overhead they introduce for developers is almost never worth any benefit you might see. Also, remember that large structs must be copied whenever they are passed or assigned to a variable, and can actually be a performance problem.
TL;DR you probably shouldn't use structs in your code, and they don't really have anything to do with immutability.
In C#, I have a struct like this:
public struct Slab
{ public float[] sizeM;
public string textureSrc;
//more members, not relevant here...
}
And another like this:
public struct Tombstone
{ public Slab mainSlab;
public Slab? basing;
//more...
}
Now, I want to modify members of basing:
uiState[0].stone.basing.Value.sizeM[2] = Int32.Parse(breadthField.Value) / 100.0f;
uiState[0].stone.basing.Value.textureSrc = fileName;
(uiState[0].stone is of type Tombstone)
First of these two calls works correctly, as I'm just changing a member of the array in basing, not the array itself. However, the second complains:
Cannot modify the return value of 'Slab?.Value' because it is not a variable
It works if I do the same to mainSlab which is not nullable. Is there a way to do this without copying the whole basing to a local variable for changes?
Is there a way to do this without copying the whole basing to a local variable for changes?
No, because Nullable<T> doesn't provide direct access to the underlying value field. You can't modify it "in place".
There are all kinds of little issues like this when you use mutable structs. I'd strongly advise you to use classes or immutable structs whenever possible, to avoid these corner cases.
Frankly, the main error here is almost certainly: having a mutable struct. Now, there are scenarios where mutable structs make sense, but those scenarios are narrow, and this almost certainly isn't one of them.
Frankly, your code will be much easier to rationalize if you stop doing that; with recent C#, you can even use readonly struct to help enforce this (and to get better behaviour with in):
public readonly struct Slab
{ public readonly float[] sizeM;
public readonly string textureSrc;
//more members, not relevant here...
}
(personally I'd also consider properties instead of public fields, but that is a separate issue)
Then it becomes obvious that you can only assign the entire object:
Slab? foo = ...
... some logic
foo = new Slab(size, textureSource); // perhaps taking new values from the old
The only other alternative is basically to do the same thing anyway:
Slab? foo = ...
// ...
var innerVal = foo.GetValueOrDefault(); // or .Value if you've already null-checked
// ...
innerVal.textureSrc = ...
foo = innerVal;
There may be many possible fixes for this "problem", depending on the rest of your design and requirements... For example:
public struct Tombstone
{
public Slab mainSlab;
public Slab basing;
public bool hasBasing => basing.sizeM != null;
//more...
}
To be honest I never user Nullables... Nullable value types, what's next, global rvalues?
I'm trying to think through a new class I'm trying to implement, and have an idea that I'm not sure is good or bad. I want to create a class that holds device settings (ex. inch vs. metric) as well as codes that correspond to the settings. I think it would be nice to have code that looks like this:
Device myDevice = new Device();
myDevice.units = Device.Inches;
myDevice.MoveTo(1,2,3, Device.Rapid);
and the Device class file would be:
class Device
{
public static DeviceUnit Inches = DeviceUnit("G21");
public static DeviceUnit Metric = DeviceUnit("G20");
public static DeviceMovement Rapid = DeviceMovement("G00");
public static DeviceMovement Feed = DeviceMovement("G01");
public DeviceUnit units;
public Device()
{
// Default to metric system
units = Device.Metric;
}
public Device(DeviceUnit customUnit)
{
units = customUnit;
}
public MoveTo(float x, float y, float z, DeviceMovement movement)
{
string command = string.Format($"{units.gcode} {movement.gcode} ");
command += string.Format($"X{x} Y{y} Z{z}\r\n");
Debug.Write(command);
}
}
Device Unit struct:
public struct DeviceUnit
{
public string gcode;
public DeviceUnit(string code)
{
gcode = code;
}
}
DeviceMovement struct:
public struct DeviceMovement
{
public string gcode;
public DeviceUnit(string code)
{
gcode = code;
}
}
My worry is I might end up being 'overkill' on the amount of structs I use. Already I'm thinking I should make another to store Incremental (G90) vs Absolute (G91) positioning. I'd like to make this flexible so that in the future I can load the gcode strings from an XML configuration file so that I can quickly create new XML files for new machine configurations.
Is using multiple structs too overkill for this task?
Should I combine the structs together somehow?
The struct have a meaning if it has multi properties that represent complex object.
I find that your struct DeviceUnit, DeviceMovement are only one property of type string, so why struct ?
let DeviceUnit, DeviceMovement string property. but wait :)
Q: Is using multiple structs too overkill for this task?
A: No, Struct is not overkill if it is used to describe an object (which may be complex device property) with many properties.
example:
public struct Dimension
{
//avoid using constructor. You can initialize with object initializer
public int x;
public int y;
public int z;
}
for example: All devices of windows are stored in WMI classes like The Win32_Printer WMI which has more than 40 property, and most of properties are a complex object.
q: Should I combine the structs together somehow?
A: simply you define a class named Device which have properties and method.
If one of the properties is a complex object, it should be of type struct or class.
You build Object model for the device , so select the type of the properties carefully.
but in your code , really your are not in need to the struct at all , use simple properties like:
public static string Inches {get;set;} = "G21"; // in c#6 you can initialize properties
My Question: Why Static properties?
My Question: Why you initialize properties with default values.
A: You can create xml file for every device and load it during object instantiation, and this give you more capability:
Use one class (or more specialized classes) to represent your device
You can add the following method to your device class:
public LoadDevice(string xmlFilename)
{
// read xml file , e.g Linq to xml
// set properties
}
Here your ceiling is the sky :)
BTW, you should use new keyword if the struct has constructor. so it should:
public static DeviceUnit Inches = new DeviceUnit("G21"); //:)
I have been working on a project for my c# class at school. And I have a very simple question I think. But I have been unable to find an answer anywhere. I keep getting results about how to make a list of structs. I want to know how to access a list inside a struct?
So here is the struct given to us by our teacher and that we must use for this assignment:
[Serializable]
struct Name
{
public string firstName;
public string lastName;
}
[Serializable]
struct Movie
{
public string title;
public string year;
public Name director;
public float quality;
public string mpaaRating;
public string genre;
public List<Name> cast;
public List<string> quotes;
public List<string> keywords;
}
struct MovieList
{
public int length;
public Movie[] movie;
}
Now I have tried accessing quotes and keywords in the following two ways and both have produced errors:
1.
string quotes;
MovieList ML = new MovieList();
quotes = Console.ReadLine();
ML.movie[0].quotes[0] = quotes;
2.
string quotes;
MovieList ML = new MovieList();
quotes = Console.ReadLine();
ML.movie[0].quotes.Add(quotes);
A struct is a Value type and as such, using a struct to carry all of this information makes it very inefficient because every time you pass it as an argument the whole contents of the struct will need to be copied, etc. a better approach would be to use a Class, which is a Reference type and it's reference is what gets passed around.
As far as how to access your struct members, here's an example:
MovieList m =new MovieList();
m.movie = new Movie[10];
m.movie[0].title="The Girl with the Dragon Tatoo";
Console.WriteLine(m.movie[0].title); //The Girl with the Dragon Tatoo
UPDATE:
Showing how to access quotes:
MovieList m =new MovieList();
m.movie = new Movie[10];
m.movie[0].title="The Girl with the Dragon Tatoo";
m.movie[0].quotes = new List<string>();
m.movie[0].quotes.Add("Hello World");
Console.WriteLine(m.movie[0].title); //The Girl with the Dragon Tatoo
Console.WriteLine(m.movie[0].quotes[0]); //Hello World
Your MovieList struct contains an array of Movie. The array isn't being initialized.
Why not just make a List<Movie> instead of a separate struct or class?
thanks for being honest about your homework. The first problem I see is that you are trying to use the list before they are initialized. Inside the structures, brand-new list are referencing to null. You have to initialize them. Please do a research about struct initialization.
Make these classes rather than structs. For every Movie in your MovieList class you will have to create a new instance of Movie so you can add to the quotes list. Otherwise it wont be initialised.
Structures should generally avoid exposing fields or properties of mutable class types, except in cases where the struct will be used by code which is merely interested in the identity of the objects referred to therein, rather than their content. Suppose one has structures m1, which contains information about some movie, and m2, which is initially blank. If one executes code:
m2 = m1;
m2.year = 2012;
m2.keywords.Add("dinosaur")
Then m1.year will be unmodified, but m1.keywords will have "dinosaur" added to it (since m1.keywords and m2.keywords both refer to the same mutable List<string>.
It's fine for structs which are used as data-holders to expose read-write fields of logically-immutable class types, or value types which don't contain any mutable class types, but structs which hold mutable reference types often have weird semantics and should be avoided when practical.
Use the static modifier to declare a
static member, which belongs to the
type itself rather than to a specific
object.
???
My encounter with this static keyword occurred when I defined a variable public int abc. When the value of this variable changed withing the brackets of while, or within the brackets of if, or within the brackets of methods, these changes were not valid, were not reflected, were not know outside the brackets. So just a hit trial. I made the variable static and all problems solved.
But why??
The difference between a static and a non-static member (not variable) is that a static member is unique over the whole runtime of a program (i.e. there is only one static member instance) whereas a non-static member is associated with an object instance (i.e. there is a member instance for each instance of the corresponding object). This is in a bit more words what the definition says.
How this all applies to what you wrote in regard to changes not reflected im not too sure - maybe you should post the corresponding code.
I did not understand what you meant but
static variables are variables at the class level - they do not belong to an instance of an object but to the class itself. They can be used and accessed without instantiating any instance.
An instance (non static) variable on the other hand belongs to the instance itself.
If you have a class:
public class Car {
public static readonly int Wheels = 4;
public static int Count {get;set;}
public string Make {get;set;}
public string Model {get;set;}
public int Year {get;set;}
public Car() { Car.Count = Car.Count + 1; }
public string SoundOff(){
return String.Format("I am only 1 out of {0} car{1}",
Car.Count, (Car.Count > 0 ? "s" : String.Empty));
}
}
Then, every time you create a car, the count will increase by one. This is because the Count property belongs to the Car class, and not to ever object you've created.
This is also useful because every car can have knowledge of the Car.Count. So, if you created:
Car sportster = new Car {
Make="Porsche", Model="Boxster", Year=2010 };
sportster.SoundOff(); // I am only 1 out of 1 car
You can do other processing and Count will be known to all objects:
Car hybrid = new Car { Make="Toyota", Model="Prius", Year=2010 };
hybrid.SoundOff(); // I am only 1 out of 2 cars
sportster.SoundOff(); // I am only 1 out of 2 cars
So, in other words, you should use static when you want something to:
Be accessible at the class-level so all objects know of it (Car.Count instead of hybrid.Count)
Represent the class and not the object (Car.Wheels won't change)
There are other reasons to use static, like Utility classes, extension methods, etc. But this should answer your question about the MSDN wording.
It's probably because you're creating multiple copies of the class, and each class has its own values for that member.
By change it to static, all instances share the same copy of the member variable.
The behavior that you're observing probably indicates a problem in your while and if expressions. If you post some sample code, I might be able to help further.