Hi all kindly help me to understand why cant we define Arrays in structs in c#
i tried the other asked question but most of them suggests to use class instead of a struct.
that is ok for implementation purpose but i want to understand why can't we define arrays in structs.
You can have an array in a structure, but that is quite pointless in most cases.
An array is an object, so the structure will only contain a reference for an array. If you create an array and assign to the reference, the array is created on the heap. The usual reason for using a structure is to avoid creating objects on the heap.
You can but you have to initialize the array in all constructors because structs require that you assign values to all members in the constructor(s).
public struct YourStruct
{
public char[] arr;
public YourStruct(int size)
{
arr = new char[size];
}
}
Like others have mentioned, if you are creating an ARRAY of OBJECTS (not value types) then a struct is not appropriate to begin with.
Look here: How to initialize char array in struct
Related
If I have a number of structs that I want to store:
type Stuff struct {
a string
b string
}
I can do it with a slice, but it seems like it would use less memory to use a proper set structure.
Unfortunately Go doesn't have a set structure. Everyone recommends using map[Stuff]struct{} but that doesn't work because Stuff is a struct. Anyone have any good solutions? Ideally without having to download a library.
Usually set and map data structures require more memory than storing a list of values in plain array or slice as set and map provide additional features efficiently like uniqueness or value retrieval by key.
If you want minimal memory usage, simply store them in a slice, e.g. []Stuff. If you use the values in multiple places, it might also be profitable to just store their pointers, e.g. []*Stuff and so each places that store the same Stuff values can store the same pointer (without duplicating the value).
If you only want to store unique struct values, then indeed the set would be the most convenient choice, in Go realized with a map.
There's nothing wrong with map[Stuff]struct{}, it works. The requirement for the key type for maps:
The comparison operators == and != must be fully defined for operands of the key type; thus the key type must not be a function, map, or slice.
Stuff is a struct, and structs in Go are comparable if:
Struct values are comparable if all their fields are comparable. Two struct values are equal if their corresponding non-blank fields are equal.
If your Stuff struct is what you posted, it is comparable: it only contains fields of the comparable type string.
Also note that if you want a set data structure, it's clearer if you use bool as the value type (e.g. map[Stuff]bool) and true as the value, and then you can simply use indexing to test if a value is in the map as the index expression yields the zero value of the value type (false for bool) if the key (Stuff in your case) is not in the map, properly telling the value you're looking for is not in the "set". (And if it is in the map, its associated true value is the result of the index expression - properly telling it is in the map).
As icza said, a map of structs is a valid option.
But instead of implementing the Set yourself, I would use one of the new generic implementations that are out there since Go 1.18.
See this one for example: https://github.com/amit7itz/goset
package main
import (
"fmt"
"github.com/amit7itz/goset"
)
type Stuff struct {
a string
b string
}
func main() {
set := goset.NewSet[Stuff]()
set.Add(Stuff{a: "1", b: "2"})
set.Add(Stuff{a: "2", b: "3"})
set.Add(Stuff{a: "2", b: "3"})
fmt.Println(set) // Set[main.Stuff]{{2 3} {1 2}}
fmt.Println(set.Len()) // 2
}
I have a simple function:
StudentType* SortStudentsByName(const StudentType* student, int numStudents)
{
StudentType* returnStudent = new (nothrow) StudentType[numStudents];
returnStudent = student; // error
}
it keeps saying Type const StudentType* cannot be assigned to StudentType*, which is ridiculous because its the same exact type, one is just a constant.
If i remove the const from the function parameter list, it works.
Im not allowed to remove the const though, because that array shouldn't be modified.
A couple important things:
(1) Both arrays are constructed at runtime to the same size, ensured by the other parameter.
(2) bitcopy should handle this, and it handles the non-const version.
Is there any way to make this work, or do i have to do something different?
It is not the same. You are trying to assign const pointer to a non const pointer. Another words: trying to assign Mutable pointer to a constant StudentType to a non-const pointer.
It does make sense to change something that is declared const to no-cont, meaning you could change a value of a constant.
What you are trying to do is to copy one object to another using shallow copy. in order to do so, you must copy object to another object not pointer to a pointer. you have to dereference pointers.:
*returnStudent = *student
Or if structure contains pointer types, shallow copy will not do. You will have to copy each member taking care of copying memory pointers point to, or write copy constructor.
I'm trying to implement a toy search algorithm and need to maintain a set of explored states. A state is a struct:
type VWState struct {
botLocation VWCoords
dirtLocations []VWCoords
}
My first thought was that a simple Set could be implemented using a map[VWState]bool, but I can't seem to figure out a way to make it work. If I try to use a VWState as a key to a map, I get the following panic:
Panic: runtime error: hash of unhashable type vw.VWState (PC=0x40EB0D)
Is there a way to make this work? Can I implement a custom hashing function for the struct, or should I be looking at some other ways to implement this?
Any help would be greatly appreciated.
You can use a pointer to your struct as a map key:
map[*VWState]bool
If you want to be able to compare equivalent structs, you can create a method to output a key for the map. String() would be convenient, since you could also use it to print your struct, or tie in a hash function and output something shorter, even an int.
Something as simple as this may suffice, though you could make the output shorter if you like (being careful not to recursively call String() in your format line):
func (s VWState) String() string {
return fmt.Sprintf("%#v", s)
}
func main() {
m := make(map[string]bool)
s := VWState{}
m[s.String()] = true
}
If there is a sensible maximum length for dirtLocations then you could use an array instead of a slice. Arrays are hashable (provided the element is hashable).
type VWState struct {
botLocation VWCoords
dirtLocations [4]VWCoords
}
You'll then need to either add a count of the number of valid dirtLocations or detect the zero value of VWCoords to work out how many slots in dirtLocations are valid.
I have code like this:
struct MyStruct {
immutable int id;
immutable int value;
this() #disable;
this(immutable int pId) {
id = pId;
value = getValueById(id);
}
}
void main() {
MyStruct structs = new MyStruct[](256); // No default initializer
foreach(ulong id, MyStruct struct_; structs) {
structs[id] = MyStruct(id); // Cannot edit immutable members
}
}
I know I could just initialize a dynamic array and add to it, but I'm interested to see if there is a more efficient way of doing this. I'm mostly concerned about how it'll have to reallocate every time while it really knows how much memory it needs in advance.
Simplest solution is to use the dynamic array and call the .reserve method before doing any appends. Then it will preallocate the space and future appends will be cheap.
void main() {
MyStruct[] structs;
structs.reserve(256); // prealloc memory
foreach(id; 0 .. 256)
structs ~= MyStruct(id); // won't reallocate
}
That's how I'd do it with dynamic arrays, writing to individual members I don't think will ever work with immutability involved like this.
BTW if you wanted a static array, calling reserve won't work, but you can explicitly initialize it.... to void. That'll leave the memory completely random, but since you explicitly requested it, the disabled default constructor won't stop you. (BTW this is prohibited in #safe functions) But in this case, those immutable members will leave it garbage forever unless you cast away immutability to prepare it soo.. not really workable, just a nice thing to know if you ever need it in the future.
In Java, all objects inherit from java.lang.Object. In Go, all types/structs implement the empty interface interface {}. Is there any similar construct in the Rust language?
If the answer is no, what makes it unnecessary? Is it because all entities in Rust (except modules) can be parameterized by type? Does that remove the need for a common "supertype" or common Trait shared by all Rust entities/structs/enums?
Yes, there is a trait. It is std::any::Any.
From the docs:
The Any trait is implemented by all 'static types, and can be used for dynamic typing
The way I understand it, if not completely unnecessary, it is less necessary in Rust to have a base type.
Note that the introduction of parametric polymorphism (generics) has removed most of the use cases for Object also in java.
With Object you can implement a "generic" method that can work with any kind of java type. On the other hand, when you have an Object you can't do much with it... You have to cast it back to the actual subtype to use it.
For instance, the old non-generic version of java collections worked with Objects, This means you had to work like this (sample is straight from this post on Oracle's site):
LinkedList list = new LinkedList();
list.add(new Integer(1));
Integer num = (Integer) list.get(0);
add takes an Object (so you can use the collection with any type). But get returns an Object too, so you have to cast it back to Integer based on the knowledge that you (the programmer) have on what you originally inserted in the LinkedList. There's very little type safety here.
The new generic version of the same container, since java 1.5, is:
LinkedList<Integer> list = new LinkedList<Integer>();
list.add(new Integer(1));
Integer num = list.get(0);
Now you have a list of Integer, so add takes Integer and get returns Integer. Object is nowhere to be seen any more (although due to type erasure it's just there, barely hiding under the hood...)
Note that Go's main use of interface{} stems from the fact that Go does not have generics. The main pattern of use for interface{} is roughly the same. You use it when you have to work with multiple types and you sort-of cast it (although in a safer way and with a more elegant pattern) back to a more useful type before using it.
With that in mind, you could theoretically use Any in Rust in the same way (checking actual type and casting to it before using it). It's just that you will likely not find many cases where this might be useful.
The code below works on rustc 0.13-nightly (2015-01-01), although I'm sure there are better ways to write it...
use std::any::{Any, AnyRefExt};
// just a couple of random types
struct Foo {
a: f64
}
enum Bar {
Baz(int),
Qux
}
fn main() {
// create an array of things that could have any type
let anything = &[&1i as &Any, &Foo{a: 2.} as &Any, &Bar::Qux as &Any];
// iterate and print only the integer
for &any in anything.iter() {
if any.is::<int>() { // check if type is int
match any.downcast_ref::<int>() { // cast to int
Some(a) => { println!("{}", *a); }
None => panic!()
}
// or just (shorter version of the match)
println!("{}", *any.downcast_ref::<int>().unwrap());
}
}
}