How should i implement, in C#, a class containing a property with the type of something and then that something example :
public class MyObject{
public someEnum e { get; set;}
public Object ObjectDependentOnE { get; set; }
}
I want to be able to return the right type for my object which depends on my enum.
for example if e = 1, my object is of type T1...
or maybe I trying to do somethng wrong
any idea?
I am unsure of what you are really trying to do, but it appears that generics is what you are looking for:
public class MyObject<T>
{
public T SomeProperty{get;set;}
}
You can constraint T to classes that implement a given interface.
Usage would be:
MyObject<SomethingClass> something = new MyObject<SomethingClass>;
I'm not sure what your use case would be - more information might help answer this better, but from my guess, you may want to consider making a factory class instead. Something like:
class MyClass
{
public SomeEnum E { get; set; }
// This might be better as : public Object GetTheObject(SomeEnum E) and eliminating the above property
public Object GetTheObject()
{
switch(this.E)
{
case E.Something:
return new MySomethingObject(); // Or return an instance that already exists...?
default:
return new MyDefaultObject();
}
}
}
This could also be a property with a getter and setter, and get and set the specific object type.
However, I recommend considering rethinking the approach - this seems like a very error-prone design, since it has no type safety at compile time, and is very confusing from the consumer's POV.
Related
I have a program where I use a class store settings. I need it to use set and get functions to change and store settings. I have tried this, and I don't get it to work. Can anyone help me with this one?
private enum _Difficulty { Easy, Normal, Hard };
public void SetDifficulty(Difficulty)
{
_Difficulty = Difficulty;
}
public enum GetDifficulty()
{
return _Difficulty;
}
Is there no way to use enums in a class with get and set?
I also need this with bool and int.
There are several things wrong here:
Your enum is private, but your methods are public. Therefore you can't make your methods return type be the enum type, or have parameters with that type
Your SetDifficulty method has a parameter of just Difficulty - is that meant to be the parameter name or the type?
Your SetDifficulty method is trying to set the type rather than a field
Your GetDifficulty method is trying to use enum as a return type, and is then returning a type rather than a field
Basically, you seem to be confused about what your enum declaration is declaring - it's not declaring a field, it's declaring a type (and specifying what the named values of that type are).
I suspect you want:
// Try not to use nested types unless there's a clear benefit.
public enum Difficulty { Easy, Normal, Hard }
public class Foo
{
// Declares a property of *type* Difficulty, and with a *name* of Difficulty
public Difficulty Difficulty { get; set; }
}
You can use get/set methods if you really want to make your code look like Java instead of C#:
public enum Difficulty { Easy, Normal, Hard }
public class Foo
{
private Difficulty difficulty;
public void SetDifficulty(Difficulty value)
{
difficulty = value;
}
public Difficulty GetDifficulty()
{
return difficulty;
}
}
Once you specify an enum using the enum keyword, that enum acts as a type, like a class or struct would.
Here's how you'd implement a property with a custom enum:
public enum _Difficulty { Easy, Normal, Hard };
public _Difficulty Difficulty { get; set; }
You code tries to assign Difficulty a value, when in fact Difficulty is the name of the enum type. I would encourage use of getters and setters as properties instead:
public enum Difficulty { Easy, Normal, Hard };
private Difficulty _difficulty;
public Difficulty CurrentDifficulty
{
get { return _difficulty; }
set { _difficulty = value; }
}
This way you can add additional code in the setter for special conditions. To use it you simply do the following:
//set
CurrentDifficulty = Difficulty.Easy;
//get
Difficulty theDifficulty = CurrentDifficulty;
The enum you want to use needs to be public. You also need an instance of that enum to store the value you're setting, you're currently setting it to your enum's declaration. Then you want to use the same enum type for what your class stores and what you pass in.
public enum Difficulty { Easy, Normal, Hard };
public Difficulty { get; set; }
There are a number of issues here:
Your enum is private, so nothing will be able to call SetDifficulty to provide it with a value from that enum. Indeed, the compiler won't allow this.
The argument to SetDifficulty is just a type, it also needs a variable name. Also a compiler error.
You're trying to get/set the value of the enumeration itself, rather than a class-level variable of the type of the enumeration. This too won't compile.
It looks like you want to do this:
public enum Difficulty { Easy, Normal, Hard }
public Difficulty DifficultySetting { get; set; }
Note that I had to change the name of the property to DifficultySetting because it conflicts with the enum name. Yours used an underscore, which would also solve that problem. However I always found that underscores are for private members and if you want consuming code to use this enum then it would need to be public. Decorating a public member with things like underscores distracts from the semantics of the name itself. In any event, the semantics are up to your personal preference, so you can modify these names as you see fit.
I'm not sure you are using them correctly. This might help...
private enum Difficulty { Easy, Normal, Hard };
private Diffuculty theDifficulty;
public void SetDifficulty(difficulty d)
{
theDifficulty = difficulty;
}
public Difficulty GetDifficulty()
{
return theDifficulty;
}
An enum is a type not a variable. Something like this would work:
public enum Difficulty { Easy, Normal, Hard };
private Difficulty _Difficulty;
public void SetDifficulty(Difficulty difficulty )
{
_Difficulty = Difficulty;
}
public Difficulty GetDifficulty()
{
return _Difficulty;
}
or more succinctly as an Auto Property:
private Difficulty Difficulty {get; set;}
Note that the enum has to be public if you want it to be accessible from public methods.
public class TestClass
{
const MyType SOMECONSTANT = null;
protected string TestString { get; set; }
}
public class MyType
{
protected string FieldA { get; set; }
}
The above code is valid and it compiles. Why does C# allow a reference type const with null? How can I use this SOMECONSTANT as this is going to be null always?
it could used as a placeholder that will at a some point later in the development cycle hold an instance of the specified object. Generally constants are used as something to compare against. Taking that idea and assuming that programmer B is going to implement and instantiate the object PERFECT_TYPE later you could say something like
const MyType PERFECT_TYPE = null;
and later I might have
if (myInstance.Equals(TestClass.PERFECT_TYPE)) { /*do stuff*/ }
Although in this situation I'd point out you'd need an implementation of MyType.Equals() but you get the idea. Things like this are not uncommon in stubbing, particularly in agile development. I would say that a stub would be more likely to be a property than a constant but, each tool for its purpose...
EDIT: Hopefully this helps, understand what I am trying to do.
I have a object returned which is of type Object, within this object I have a int value,
based on this int value I want to be able to use a enum to tell me what specific object a should case this object to.
The Enum holds all possible casings.
I will receive a generic object (of type object) which can be one of many different more specific objects say in this case of type Model. I want to be able to look inside the object for an int value which will tell me which cast to use.
For instance a have objectA and it has a int value set to '2' within the object, I want to cast this object to my specific object based on my enum value 2, which is set to a specific type.
This may be very simple but cannot work out how you would so this and if it is possible, thank you.
Thanks.
If you mean you want to change the type of the objectA variable at exection time, the answer is no. The compiler needs to know the type of the variable for all kinds of things which are done at compile time.
If you're using C# 4, you may be able to use dynamic to help you - but it's not really clear what you're trying to achieve. In many cases it's a better idea to create a common interface which all of your types implement, and then just make the type of the variable the interface type. That's not universally applicable, but it's a good idea when it works.
Are you trying to typecast one enum to another?
Enum Type1
{
A
B
};
Enum Type2
{
A,
B
};
Type1 type1 = Type1.A;
if(Enum.IsDefined(typeof(Type2), type1.A.ToString())
{
Type2 type2 = (Type2)Enum.Parse(typeof(Type2), type1.A.ToString());
//type2 now holds Type2.A
}
EDIT
If you want to change type of an object at runtime, it is not possible.
If you just mean casting, (same object different representation corresponding to implemented interfaces, base class, etc), it is possible, but here object type does not change.
It's a little hard to understand what you want. But this is my take on it. All your classes would need to implement interface ITypeContainer to be able to extract the enum value.
void Main()
{
....
....
CastToType((ITypeContainer)myObject);
}
public void CastToType(ITypeContainer obj)
{
switch (obj.ObjectType)
{
case TypeEnum.Test1:
var o1 = (Test1)obj;
break;
case TypeEnum.Test2:
var o2 = (Test2)obj;
break;
}
}
public class Test1 : ITypeContainer
{
public TypeEnum ObjectType{ get; set; }
}
public class Test2 : ITypeContainer
{
public TypeEnum ObjectType{ get; set; }
}
public enum TypeEnum
{
Test1,
Test2,
Test3
}
public interface ITypeContainer
{
TypeEnum ObjectType{ get; set; }
}
Say I have an object,
Class A<T, T2>
{
public T MyObject {get;set;}
public IList<A<T2>> MyChildren {get;set;}
}
Problem is, sometimes I dont have children, so I dont want to declare the children type aka T2, any idea? I cannot pass in like
A a = new A<string, Nullable>(); as it is throwing an error.
Thanks
There's no way to specify a "null" for a Generic Type parameter - if you declare them on the class, they're mandatory when you use that class.
If you think about it, this makes sense, because without T2, your class will be partially undefined, which isn't something that machines can handle well.
What you probably need to do is to split your class into two. First, your class with no children:
class Widget<T>
{
public T MyObject { get; set; }
}
Then, an extension that adds support for children:
class WidgetWithChildren<T,T2>: Widget<T>
{
public IList<Widget<T>> MyChildren { get; set; }
}
Though, that's only a partial solution, as you don't get a way to handle grandchildren.
Nullable is a genric it self so you have to do something like
new A<string, Nullable<?>>();
You use Nullable to make Value types (e.g. int) able to be null but if you use a Referense Type (e.g. class) it can be null anyway.
My tip is to use a base class for A, if you don't have one use Object.
new A<string, Object>();
I swear I have seen an example of this but have been googling for a bit and can not find it.
I have a class that has a reference to an object and need to have a GET; method for it. My problem is that I do not want anyone to be able to fiddle with it, i.e. I want them to get a read only version of it, (note I need to be able to alter it from within my class).
Thanks
No, there's no way of doing this. For instance, if you return a List<string> (and it's not immutable) then callers will be able to add entries.
The normal way round this is to return an immutable wrapper, e.g. ReadOnlyCollection<T>.
For other mutable types, you may need to clone the value before returning it.
Note that just returning an immutable interface view (e.g. returning IEnumerable<T> instead of List<T>) won't stop a caller from casting back to the mutable type and mutating.
EDIT: Note that apart from anything else, this kind of concern is one of the reasons why immutable types make it easier to reason about code :)
Return a reference to a stripped-down interface:
interface IFoo
string Bar { get; }
class ClassWithGet
public IFoo GetFoo(...);
If the object isn't too complicated/extensive then write an wrapper around it.
for example:
class A {
public string strField = 'string';
public int intField = 10;
}
class AWrapper {
private A _aObj;
public AWrapper(A aobj) {
_aObj = A;
}
public string strField {
get {
return _aObj.strField;
}
}
public int intField {
get {
return _aObj.intField;
}
}
}
So now all you do is give your client code an instance of the AWrapper class so that they may only use what you allow them to see.
this may get a bit complicated and may not scale well if your base class is not set in stone, but for most simple situation it may just do the trick. I think this is called a facade pattern(but don't quote me on that =) )
This isn't possible. Get and set accessors to reference types get and set the reference to the object. You can prevent changes to the reference by using a private (or internal) setter, but you cannot prevent changes to the object itself if it's exposed by a getter.
Your question reads like you're looking for:
public PropertyName { get; private set; }
But then, given the answers so far I'm not sure I'm interpreting your question correctly. Besides, who am I to question Jon Skeet? :)
i agree with ReadOnlyCollection
See my simple code:
private List<Device> _devices;
public readonly System.Collections.ObjectModel.ReadOnlyCollection<Device> Devices
{
get
{
return (_devices.AsReadOnly());
}
}
ReadOnlyCollection dosen't has Add method so user cant add properties to it.BUT ther is no warranty that if user can modify objects by calling their methods....
I have faced this problem in a certain way.
I have a CategoryViewModel class, which have a property Category that I want private read-only :
public CategoryViewModel
{
private Category { get; }
}
In fact, I want it to be exported as read-only to other class. However I can't do such thing.
In my case (maybe it will help some other guys), I want to add it to a repository. The only way that I've found is to have a function with the repository as param 1, and an Action as param 2 :
public void ApplyAction(ICategoryRepository repo, Action<ICategoryRepository, Category> action)
{
action(repo, Category);
}
Like that, from elsewhere, I can do such thing :
categoryViewModel.ApplyAction(_repository, (r, c) => r.MarkForInsertOrUpdate(c));
This can help other to expose there property only for certains cases and can manage them.