Enum type in constructor - c#

So I have to initiate an object from a class into the main form, but the arguments I have to put in the constructor are from an enum type I made in that class.
private List<Geluidsfragment> fragmenten;
private enum ThemaSoorten
{
Muziek,
Luisterboeken,
Cabaretshows
}
^this part is now outside the class, as was advised.
// Constrcutors
public BGExperience(ThemaSoorten thema)
{
fragmenten = new List<Geluidsfragment>();
this.thema = thema;
}
These are the fields and constructor for the field. Below is the initiation of the object of this class I need.
public GeluidsfragmentForm()
{
InitializeComponent();
BGExperience bgExperience = new BGExperience("Muziek");
}
So the overload has to be of the type ThemaSoorten and it has to be in the enum, but at this point it gets stuck.
Anyone know how to solve this?

You should make first your enum to be public and then try this one:
BGExperience bgExperience = new BGExperience(BGExperience.ThemaSoorten.Muziek);
If you don't make your enum to be public, you will not be able to access it outside your class let alone to create an instance of your class.
Update
As correctly Sriram has already pointed out in his comments, it would be a better design approach to not make this enum to be a nested type. You could declare it outside of your class, like:
public enum ThemaSoorten
{
Muziek,
Luisterboeken,
Cabaretshows
}
and then create a new BGExperience object as below:
var bgExperience = new BGExperience(ThemaSoorten.Muziek);
Important Note (thanks Selman22)
You can't declare an enum with the way you have already done it. This couldn't even compile. Furthermore, you should take an error message while you were typing this. Anyway, the correct way of defininit an enum is the following:
public enum EnumName
{
Member1,
Member2,
Member3
}
In place of EnumName you should put the name of your enum and in place of Member1, Member2 and Member3 the names of the items in your enum. If you want this items have specific values, you should do it like:
public enum EnumName
{
Member1 = 1,
Member2 = 2,
Member3 = 3
}

Or perhaps you want to provide string value of the enum to the constructor, then here is how it will work:
BGExperience bgExperience = new BGExperience((BGExperience.ThemaSoorten)Enum.Parse(typeof(BGExperience.ThemaSoorten), "Muziek"));
Make sure to make the enum public for that. Otherwise you have to provide string in the constructor and parsing it to the enum value within the constructor.

BGExperience bgExperience = new BGExperience(ThemaSoorten.thema1);

Related

How can I add a default constructor and have it call another constructor and use the default values?

I have this code:
public class NewFrame
{
public NewFrame(string iconSource = Const.Car,
string iconColor = Const.Red)
{
When I try and use it then it's telling me I am missing a default constructor. How can I add one of these and still make the code use the default values for iconBackgroundColor and IconSource? I thought that adding in those defaults with the = Const. would make it work but it seems like it doesn't think my constructor is a default (with no params).
You just have to add another empty overload and call the required constructor with defaults. See below:
public class NewFrame
{
public NewFrame() : this(Const.Car, Const.Red){
}
public NewFrame(string iconSource,
string iconColor)
{
...
}
}
By having two optional parameters, you don't actually create 4 different constructor declarations under the hood (one with both parameters, one with the first parameter, one with the second parameter, and one with neither). There is still only one constructor, with two parameters. It's just that C# recognises that the parameters are optional, and has syntactic sugar to let you omit them when you call the constructor.
However, if you use reflection to create an instance of your class (probably whatever the thing that requires a default constructor is doing), and you attempt to invoke the parameterless constructor, it won't find one, because there is no syntactic sugar in reflection.
Here is an example:
class MainClass
{
public static void Main(string[] args)
{
Type t = typeof(MainClass);
object o = Activator.CreateInstance(t, 1);
Console.WriteLine(o);
}
public MainClass(int a = 10)
{
}
}
If you use typeof(MainClass).GetConstructors(), it will tell you that there is only one.
To actually declare a default constructor, you can do:
public class NewFrame
{
public NewFrame(string iconSource = Const.Car,
string iconColor = Const.Red)
{
...
}
public NewFrame() : this(Const.Car, Const.Red) { }
}
For what it's worth, when I do something like this, I take the route that #VyacheslavBenedichuk's answer is showing.
I'm not sure what your complaint is. This code compiles for me:
public class TestConstructor
{
public TestConstructor(string what = Const.Car, string color = Const.Red)
{
}
public static void Test()
{
var tc = new TestConstructor();
}
public class Const
{
public const string Car = "car";
public const string Red = "red";
}
}
What do your definitions of Const.Car and Const.Red look like? Where are you seeing the error?
But, if you use something that requires a default constructor, then this will not work. For example, this will fail at runtime:
var tc2 = Activator.CreateInstance(typeof(TestConstructor));
Please, when you are reporting an error, describe it exactly - in particular say whether it's a runtime or a compile-time error, the exact wording of the error, and the context in which the error occurs. In this case (the call to CreateInstance) will result in a System.MissingMethodException: 'No parameterless constructor defined for this object.'
In this case, you need to follow #VyacheslavBenedichuk's advice

Reflection : Get the real type of a initialized auto-property (C#6)

I have a class declared like this :
public class MyClass
{
public IMyInterface1 Prop1 { get; } = new MyImplementation1();
public IMyInterface2 Prop2 { get; } = new MyImplementation2();
public IMyInterface3 Prop3 { get; } = new MyImplementation3();
//[...]
}
I would like the list of implemented types, using reflection.
I dont have an instance of MyClass, just the type.
Ex:
static void Main(string[] args)
{
var aList = typeof(MyClass).GetProperties(); // [IMyInterface1, IMyInterface2, IMyInterface3]
var whatIWant = GetImplementedProperties(typeof(MyClass)); // [MyImplementation1, MyImplementation2, MyImplementation3]
}
IEnumerable<Type> GetImplementedProperties(Type type)
{
// How can I do that ?
}
PS: I'm not sure the title is well adapted, but I have found nothing better. I am open to suggestions.
Reflection is type metadata introspection, thus, it can't get what an actual instance of a given type may contain in their properties unless you provide an instance of the so-called type.
That's the main reason why reflection methods like PropertyInfo.GetValue have a first mandatory argument: the instance of the type where the property is declared on.
You're in the wrong direction if you want to use reflection for this. Actually you need a syntax analyzer and luckily, C# 6 comes with the new and fancy compiler formerly known as Roslyn (GitHub repository). You can also use NRefactory (GitHub repository).
Both can be used to parse actual C# code. You can parse the whole source code and then get what classes are returned in expression-bodied properties.
You can't get real types without class instance, because properties are initialized only for instances. For instance of the class, you can do something like that
List<Type> propertyTypes = new List<Type>();
PropertyInfo[] properties = typeof(MyClass).GetProperties();
foreach(PropertyInfo propertyInfo in properties)
{
propertyTypes.Add(propertyInfo.GetValue(myClassInstance));
}

Instantiating collections

I'm trying to understand how the line:
private Queue<IProductable> inventory { get; set; }
It is used in the entire code below. I'm only used to seeing properties defined using simple types; so, this really confused me. Also, I'm curious why the constructor for the class Factory (below) uses:
inventory = new Queue<IProductable>();
Instead of:
Queue<IProductable> inventory = new Queue<IProductable>();
My understanding is when you instantiate an new object, you should do: CLASS/TYPE newObjectName = new CLASS/TYPE. Is the constructor even instantiating a new "inventory" object? If so, why don't I have to specify what type the object "inventory" is (in order to use it to invoke methods from the generic Collections class, Queue).
Anyway, below, is the code. I'm hoping someone can explain this in the easiest possible way for me to comprehend/remember when I need to do something similar in the future.
namespace codeExample
{
class Factory
{
private Queue<IProductable> inventory { get; set; }
public Factory()
{
inventory = new Queue<IProductable>();
}
public IProductable GetOldestItem()
{
IProductable oldestItem = inventory.First();
return oldestItem;
}
public IProductable GetNewestItem()
{
IProductable newestItem = inventory.Last();
return newestItem;
}
public void Add(IProductable productToAdd)
{
inventory.Enqueue(productToAdd);
}
}
}
My understanding is when you instantiate an new object, you should do: CLASS/TYPE newObjectName = new CLASS/TYPE. Is the constructor even instantiating a new "inventory" object?
If the type were included then it would be creating a new local variable. Currently the code is not creating a new variable, it is using the property instead, which is a part of that class's instance data (at least in this case). The property (in this specific context) acts almost exactly like a private field would. It is creating a variable that exists for the lifetime of the whole object, not just one method.
Is the constructor even instantiating a new "inventory" object?
It's creating a new queue object, yes. The property definition defines where a queue may be stored, but it doesn't create an actual queue. The constructor actually creates a queue (which is empty) and assigns is to the variable.
The private Queue<IProductable> inventory { get; set; } declares an auto-implemented property, but it could as well have been a field:
private Queue<IProductable> inventory;
This declares a private instance variable, which you can access from any method in this class, but not from derived classes or from outside the class.
Your code assigns a value in the constructor, which is always run before other code in the class:
inventory = new Queue<IProductable>();
So now from everywhere in this class you can access inventory.
I'm only used to seeing properties defined with simple types; so, this
really confused me
Why? You can define properties of any type.
Also, I'm curious why the constructor for the class Factory (below)
uses:
You can't define the type of the property again, it's already available in the current scope because it's a class property. Its type is defined at the line private Queue<IProductable> inventory { get; set; }
My understanding is when you instantiate an new object, you should do:
CLASS/TYPE newObjectName = new CLASS/TYPE
No, here is a simple counter-example in two lines:
MyType myVariable;
...
myVariable = new MyType();
private Queue<IProductable> inventory { get; set; }
is an auto property.
it's equivalent to
private Queue<IProductable> _inventory;
public Queue<IProductable> Inventory
{
get { return _inventory; }
set { _inventory = value; }
}
Thus, you just declared a member inventory, and later on you instantiate a Queue<IProductable> and store its reference to the auto property inventory.
inventory = new Queue<IProductable>();
private Queue<IProductable> inventory { get; set; } is an automatic property. The implementation of get/set are provided by the compiler.
vs
Queue<IProductable> inventory = new Queue<IProductable>();
Now, inventory is a field. Properties have backing stores and are smarter than fields. They allow a programmer to do work during get/set operations.
Is the constructor even instantiating a new "inventory" object?
Yes, in the example the constructor is setting the hidden variable (backing store).
If so, why don't I have to specify what type the object "inventory" is
(in order to use it to invoke methods from the generic Collections
class, Queue).
Because you are not declaring a new variable in the constructor. We are setting a property.
Here you could use a field instead of a property. However, I would expect an "advanced class"/Factory to use Dependency Injection and thus a public property would make sense in such a case. (Maybe you simplified the original code?)

How to define named Parameters C#

This seems like a simple question, but for some reason I can't find the answer anywhere. Basically, I'd like to be able to implement a constructor that takes NamedParameters.
By named parameters, I do not mean parameters with default values (optional parameters) such as:
public SomeMethod(){
string newBar = Foo(bar2 : "customBar2");
}
public string Foo(string bar1 = "bar1", bar2 = "bar2" ){
//...
}
A good example of what I'm trying to achieve is the AuthorizeAttribute from the System.Web.Mvc assembly. Which you can use the following way:
[Authorize(Roles = "Administrators", Users = "ThatCoolGuy")]
public ActionResult Admin(){
}
The constructor's signature in intellisense looks like the following example and I believe (please confirm) that those NamedParameters are mapping to class properties.
AuthorizeAttribute.AuthorizeAttribute(NamedParameters...)
Initiliaze new instance of the System.Web.Mvc.AuthorizeAttribute class
Named parameters:
Order int
Users string
Roles string
Please note:
The syntax of defining the parameter name when calling a method has nothing to do with optional parameters:
You can use Foo(bar1 : "customBar1"); even if Foo is declared like this: void Foo(string bar1)
To answer the question:
My guess is that this is syntactic sugar similar to the object initializers introduced in Visual Studio 2010 and therefore you can't use this for your own classes.
The behaviour you are talking about is specific for attributes and cannot be reused in "normal" classes constructors.
You don't need to "implement" anything.
The parameters can be used in the manner you describe just by existing as parameters on the constructor.
You do need to be using C# 3.5 or above, when they were introduced.
Your example will compile and run on C# 4.0 / Visual Studio 2010 without modification.
See Named and Optional Arguments (C# Programming Guide) on MSDN.
In regards to properties on the object, that do not have a corresponding constructor arguments, the exact syntax is specific to attributes and can't be replicated, though, with object initializers you can get close.
You can use the builder/constructor info pattern together with property initializers.
class PersonInfo
{
public string Name { get; set; }
public int? Age { get; set; }
public Color? FavoriteColor { get; set; }
public Person BuildPerson()
{
return new Person(this);
}
}
class Person
{
public Person(PersonInfo info)
{
// use info and handle optional/nullable parameters to initialize person
}
...
}
var p = new Person(new PersonInfo { Name = "Peter", Age = 15 });
// yet better
var p = new PersonInfo { Name = "Peter", Age = 15 }.BuildPerson();
I however don't understand, why you don't just use named parameters and provide null for indicating optional parameters.
class Person
{
public Person(string name = null, int? age = null, Color? favoriteColor = null) { /* ... */ }
}
var p = new Person(name: "Peter", age: 15);
Named parameters are NOT specific to attributes. It's a language syntax that can be used everywhere. It's fine to use properties for initialisers but you don't always want to have internals set as set properties.
Just instantiate you class using:
TheClass c = new Theclass(param3:firstValue, param1:secondValue, param2:secondValue);
With regards to this part of the question:
"I however don't understand, why you don't just use named parameters and provide null for indicating optional parameters."
The reason named parameters are nice is you don't need to provide extraneous values in parentheses, just what you want to specify, because if it's optional you shouldn't even need to put null. Furthermore, if you specify null, you are overriding any default value for that parameter which makes it optional. Being optional implies there's a default value meaning nothing passed in.
Property initialisation at instance time is purely there for convenience. Since C there has been the ability to initialise values at construction time on types. Which is handy if those values can't be specified in the constructor. I personally feel that the convenience of them has spoiled people and it get a little too liberal and make everything public get AND set. Just depends on the design and security of properties you need.
I doubt that's possible. This is something specific for attributes.
I think the closest option is to use an object initializer:
class Foo {
public string Name {get;set;}
public int Data {get;set;}
}
var foo = new Foo {Name = "MyName", Data = 12};
try to use this signature
[AttributeUsage(AttributeTargets.Class)]
before the name of your class
Please refer to MSDN specification for full description:
https://msdn.microsoft.com/en-us/library/aa664614(v=vs.71).aspx
"Each non-static public read-write field and property for an attribute class defines a named parameter for the attribute class".
Visual C# 2010 introduces named and optional arguments. Named argument able you to specify an argument for a particular parameter by associating the argument with the parameter's name rather than with the parameter's position in the parameter list.Named arguments free you from the need to remember or to look up the order of parameters in the parameter lists of called methods.
static void Main(string[] args)
{
mapingFunction(snum2: "www.stackoverflow.com", num1: 1);
}
public static void mapingFunction(int num1, string snum2)
{
Console.WriteLine(num1 + " and " + snum2);
}
here you can see that argument are passed with our their order
What you probably want to do is implement public properties in your attribute:
public class AuditFilterAttribute : ActionFilterAttribute
{
public string Message { get; set; }
public AuditFilterAttribute() { }
}
They can be accessed through Named Parameters where you apply it:
[AuditFilter(Message = "Deleting user")]
public ActionResult DeleteUser(int userId)
Hope that helps...

C# array is a field but is used like a type [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
(object) is a 'field' but is used like a 'type'
As you might have guessed from the title am I getting this error:
Invasion_server.variables.resources is a field but is used like a type
The code that is giving me that error is:
class variables
{
....
public static string[] resources = new string[30];
resources[0] = "cities_wood";
....
}
Could someone please tell me what is causing the problem, because elsewhere in the code it is working...
You should do this in some method
If you would like to initialize the members of the array outside of a constructor or method body, you would need to do so using the initializer syntax with the declaration:
class variables
{
public static string[] resources = new string[30]
{
"item one",
"item two",
...
}
}
The downside to doing so is that you'd be required to populate all 30 values. If you're looking to just populate the first, then you'll need to do so either in a constructor or method body. You could consider a static constructor, which would have the same net effect as initializing when declared; the static constructor is run the first time a member of the class is accessed. For example:
class variables
{
public static string[] resources;
static variables()
{
resources = new string[30];
resources[0] = "item one";
}
}
Try this:
class variables
{
public static string[] resources = new string[30];
static void doSomething() {
resources[0] = "cities_wood";
}
}
you were not assigning the variable within a class constructor or a method.
It's because you're trying to do operations on a variable in the class body, rather than in a method. You should only have a few things in your class body:
Fields: int myField = 0;
Methods: public void myMethod(){ }
Constructors/Destructors (just a special type of method): public MyClass(){}
So when the compiler sees anything that is the first word following a ; (meaning that it is the first word of a new line of code), it expects to see either an identifier like public, static, etc, or a Type, like int. Since it wasn't an identifier, it looked for a type, and since it wasn't a type, you got your error.
Hope that explains it pretty well.
you cannot do
resources[0] = "cities_wood";
in your class definition. Do it in a static constuctor or using a list initializer.
You have to initialize the fields in a method or constructor or all in the declaration like
class variables
{
public static string[] resources = new string[30];
public variables()
{
resources[0] = "cities_wood";
}
}
OR
public static string[] resources = {"cities_wood", "....", "more stuff", "and more stuff"};//Your 30 or les or more variables separated by a comma

Categories