I am creating the wrapper POCO classes for ENUM in Entity Framework 4 as mentioned here. I have created the wrapper for the enum as follows
public class PriorityWrapper
{
private gender _t;
public int Value
{
get
{
return (int)_t;
}
set
{
_t = (gender)value;
}
}
public gender EnumValue
{
get
{
return _t;
}
set
{
_t = value;
}
}
public static implicit operator PriorityWrapper(gender p)
{
return new PriorityWrapper { EnumValue = p };
}
public static implicit operator gender(PriorityWrapper pw)
{
if (pw == null) return gender.Male;
else return pw.EnumValue;
}
}
But I also have other ENUM apart from gender as mentioned above. Can I use generics here so I can use the same code for all ENUM occurrences.
I am new to generics, so need help from experts.
You cannot use enums as generic constraints, instead you can use.
public class EnumWrapper<T>
{
public static int Num = 1;
private T _t;
public T EnumValue
{
get
{
return _t;
}
set
{
_t = value;
}
}
public void Assign<U>(U inn) where U : struct, T
{
if (typeof(T).IsEnum)
{
EnumValue = inn;
}
}
}
and invoke it like this
var agen = new EnumWrapper<gender>();
gender g=new gender() ;
agen.Assign (g);
EDIT: Assign() is a dummy method. My intention was to show how to use enum as generic constraint.
It is not possible to have generic conversion operators. So, there can't be exact generic equivalent for above code. Besides, one cannot mention enum as generic type constraint, so casting within property implementation is also not possible (or may need some other constraint (possibly interface) to work that may result in boxing/unboxing). In short, IMO, having generic solution with reasonable performance may not be feasible.
I would suggest that you try using code generation (look at T4 templates) for creating your wrapper classes. T4 is pretty simple - refer here for few links: http://www.hanselman.com/blog/T4TextTemplateTransformationToolkitCodeGenerationBestKeptVisualStudioSecret.aspx
Related
I have
struct MyType
{
public int value;
}
How can I define an explicit operator so that it is castable to any enum ? "any" means any enum in existence.
The "convertible to any possible enum" function is already possible if it is an int and not a struct containing int. For example I can always (AnyEnum)myType.value, (SomeOtherEnum)myType.value. But I would like to be able to do (AnyEnum)myType directly without digging an int inside. My idea is naturally, utilizing implicit in some way which will treat the whole thing as int. But unfortunately implicit does not support generic, so I would have to define implicit for every enum I wish to support.
It is fine if this involves some use of C# 7.3's Enum generic constraint. But it seems even with the constraint where T : Enum I cannot cast an int to T by (T)value. ("Cannot convert type int to T)
An example use case :
if(myValue.something == something)
{
switch((MyEnum)myValue)
{
case MyEnum.A : ...
case MyEnum.B : ...
}
}
else if(myValue.something == something)
{
switch((MyOtherEnum)myValue)
{
case MyOtherEnum.A : ...
case MyOtherEnum.B : ...
}
}
Another one,
if(myValue.ValidInEnum<MyEnum>(out MyEnum validEnum)) //converted from inside with some additional logic
{
switch(validEnum)
{
case MyEnum.A : ...
case MyEnum.B : ...
}
}
If you want to convert from an enum directly instead of having to access the "value" member of your struct, yes, it is possible, here is an example:
static void Main(string[] args)
{
MyType myType;
myType.value = 1;
MyEnum myEnum = (MyEnum) myType;
Console.WriteLine(myEnum);
Console.ReadLine();
}
enum MyEnum
{
a = 0,
b = 1
}
struct MyType
{
public int value;
public static explicit operator MyEnum(MyType myType)
{
return (MyEnum)myType.value;
}
}
The output is:
b
If you want to cast from any type of enum directly to your struct, I don't think that would be possible, you can look into generics as suggested in the other answer, or maybe write a little extension helper for your type:
public static class MyTypeExtensions
{
public static T ToAnyEnum<T>(this MyType myType)
{
return (T)Enum.ToObject(typeof(T), myType.value);
}
}
Then you can write:
MyType myType;
myType.value = 1;
MyEnum myEnum = myType.ToAnyEnum<MyEnum>();
MyOtherEnum myOtherEnum = myType.ToAnyEnum<MyOtherEnum>();
It's not possible. You cannot create a cast operator for any enum type, only for concrete enum types I'm afraid you would have go through the "big hassle" of doing:
var anyEnum = (AnyEnum)myType.value;
Another way would be using something like a ToEnum method maybe:
struct MyType
{
int value;
public T ToEnum<T>() where T : struct
{
return (T)Enum.ToObject(typeof(T), this.value);
}
}
Usage:
var anyEnum = myType.ToEnum<AnyEnum>();
You could also create an explicit cast to your value type:
public static explicit operator int(MyType myType)
{
return myType.value;
}
Then you can do:
var anyEnum = (AnyEnum)(int)myType;
I admit it's not really much shorter, but this would allow to make value private for example or do any other custom logic in the conversion.
Personal Note
I don't believe this kind of design makes much sense. It just tries to answer the original question. It was interesting to think about it.
Update:
I'll accept that to get the code to work Jon's answer to this other question is correct. And this answer answers why an interface is treated like a reference type.
I'd still like to know what the difference is though. Why is an interface not treated like a reference type when it is a generic type constraint? Is their some design reason for this? I have a feeling the only reason may be "they just are".
Original question:
I am converting a class into a generic class but I found some strange behaviour with using an interface as a type parameter. The class has a field and property which are a type of interface, for example IMagic.
public interface IMagic
{
bool Magic { get; }
}
public class HasMagic
{
private IMagic _magic;
public IMagic Magic
{
get { return _magic; }
set
{
if (value != _magic)
_magic = value;
}
}
public bool IsMagical
{
get { return _magic != null ? _magic.Magic : true; }
}
}
I want to change them to instead be type T and have the class defined with the type parameter where T : IMagic. Doing this though gave me a compiler error Operator '!=' cannot be applied to operands of type 'T' and 'T'.
public class HasMagic<T> where T : IMagic
{
private T _magic;
public T Magic
{
get { return _magic; }
set
{
// Compiler error here!
if (value != _magic)
_magic = value;
}
}
public bool IsMagical
{
// But no error here!?
get { return _magic != null ? _magic.Magic : true; }
}
}
So why doesn't the generic version work? Shouldn't == and != operators work for all types?
The error only occurs in the property setter though, so it got me thinking, is the _magic field actually really a boxed IMagic or some other reference type? Indeed it can be set to null which should only work with nullable types. As the test below shows an IMagic struct (MagicStruct) works fine, but why? Changing the field and property in HasMagic to a MagicStruct gives compile errors, as you'd expect.
public class MagicTests
{
[Fact]
public void SomeMagicTest()
{
var mag = new HasMagic();
Assert.True(mag.IsMagical);
mag.Magic = new MagicClass();
Assert.False(mag.IsMagical);
mag.Magic = new MagicStruct();
Assert.True(mag.IsMagical);
mag.Magic = null;
Assert.True(mag.IsMagical);
}
}
public class MagicClass : IMagic
{
public bool Magic { get { return false; } }
}
public struct MagicStruct : IMagic
{
public bool Magic { get { return true; } }
}
If it's of any relevance I'm using .Net framework v4.5.2.
T is a type argument and can be a class or a struct, because of that the compiler won't let you perform actions that doesn't exist in a class or a struct. You can try it like this:
public T Magic
{
get { return _magic; }
set
{
// Compiler error here!
if (!EqualityComparer<T>.Default.Equals(_magic, value))
_magic = value;
}
}
Or you can just use Equals inside your code
public T Magic
{
get { return _magic; }
set
{
// Compiler error here!
if (!value.Equals(_magic))
_magic = value;
}
}
You cannot use != (==) on generic types.
a possible solution would be made IMagic to implement IComparable
public interface IMagic : IComparable
and then use CompareTo
if (value.CompareTo(_magic) != 0)
you can write your own implementation of CompareTo method
public int CompareTo(object obj) {
}
update
if you can't edit IMagic try adding a property to HasMagic class like this
public Func<T, T, bool> FuncEvaluate { get; set; }
and then check in this way
public T Magic
{
get { return _magic; }
set
{
if (FuncEvaluate != null)
{
if (!FuncEvaluate(value, _magic))
{
_magic = value;
}
}
else
{
throw new NotImplementedException();
}
}
}
and when you decide to use the class you should set the function to compare objects maybe checking typeof(T).IsValueType
T can be a value type or a reference type; you didn't contrain it. The != (and ==) operator (reference comparison) is only defined for reference types, not for value types.
There are several solutions; You can constrain T to be a reference type:
public class HasMagic<T> where T : IMagic, class
You can also use Equals(). or object.ReferenceEquals().
And maybe some other solutions I didn't think of.
Edit: I just noticed you don't even need != in the setter, so this whole problem becomes mute.
I need my enum to return a specific string, but I can't work out how to make it return a string with breaks in it without having a method to do the conversion. Is it possible to make LicenseTypes.DISCOUNT_EARLY_ADOPTER return DISCOUNT EARLY-ADOPTER without the helper method?
// All license types
public enum LicenseTypes
{
DISCOUNT,
DISCOUNT_EARLY_ADOPTER,
COMMERCIAL,
COMMERCIAL_EARLY_ADOPTER
}
// Convert enum to correct string
public static string LicenseTypeToString(LicenseTypes Enum)
{
if (Enum == LicenseTypes.COMMERCIAL)
return "COMMERCIAL";
else if (Enum == LicenseTypes.COMMERCIAL_EARLY_ADOPTER)
return "COMMERCIAL EARLY-ADOPTER";
else if (Enum == LicenseTypes.DISCOUNT)
return "DISCOUNT";
else if (Enum == LicenseTypes.DISCOUNT_EARLY_ADOPTER)
return "DISCOUNT EARLY-ADOPTER";
else
return "ERROR";
}
Firstly, a separate option from a helper method is simply to have a Dictionary<LicenseTypes, string> which you populate once. That would probably be the simplest approach, to be honest:
private static readonly Dictionary<LicenseTypes, string> LicenseDesciptions =
new Dictionary<LicenseTypes, string>
{
{ LicenseTypes.COMMERCIAL, "COMMERCIAL" },
{ LicenseTypes.COMMERCIAL_EARLY_ADOPTER, "COMMERCIAL EARLY-ADOPTER" },
{ LicenseTypes.DOMESTIC, "DOMESTIC" },
{ LicenseTypes.DOMESTIC_EARLY_ADOPTER, "DOMESTIC EARLY-ADOPTER" },
};
(As noted in comments, another alternative is a switch/case... but I personally prefer this way, as effectively you've got a data mapping, so it makes sense to use a data structure rather than an execution flow structure. It also means you can swap out dictionaries for different languages etc if you want.)
Secondly, one option would be to decorate each enum value with a [Description] attribute (or your own attribute if you want), and find that out with reflection - Unconstrained Melody has an extension method which can do that very easily:
// Throws ArgumentOutOfRangeException if the licenseType value isn't defined
// or doesn't have a description.
string description = licenseType.GetDescription();
Also, following .NET naming conventions it should be:
public enum LicenseType // Singular as it's not a Flags enum
{
Discount,
DiscountEarlyAdopter,
Commercial,
CommercialEarlyAdopter
}
A little reflection, and Attribute magic, and this should just answer it :)
Getting attributes of Enum's value
Might also make it an extension method.
here's how it should look (also added generics):
public static class MyExtensionsClass
{
public static string ToDescriptionString<T>(this T val)
where T : struct, IConvertible
{
if (typeof(T).IsEnum)
{
var type = val.GetType();
var memInfo = type.GetMember(val.ToString());
var attributes = memInfo[0].GetCustomAttributes(typeof(DescriptionAttribute), false);
return ((DescriptionAttribute)attributes[0]).Description;
}
return ""; //all paths must return a value
}
}
public enum LicenseTypes
{
[Description("DISCOUNT")]
DISCOUNT,
[Description("DISCOUNT EARLY-ADOPTER")]
DISCOUNT_EARLY_ADOPTER,
[Description("COMMERCIAL")]
COMMERCIAL,
[Description("COMMERCIAL EARLY-ADOPTER")]
COMMERCIAL_EARLY_ADOPTER
}
Thank you, guys that wrote these:
Enhance enums using extension methods
Create Generic method constraining T to an Enum
Good luck!
While it doesn't eliminate the helper method, note that in your case you could just special-case the values that you can't get using ToString:
switch (Enum) {
case LicenseTypes.COMMERCIAL_EARLY_ADOPTER:
return "COMMERCIAL EARLY-ADOPTER";
case LicenseTypes.DISCOUNT_EARLY_ADOPTER:
return "DISCOUNT EARLY-ADOPTER";
default
return Enum.ToString();
}
I use this from Google's dotnet client - StringValueAttribute.cs
and Utilities.cs
public enum LicenseType
{
[StringValue("DISCOUNT")] Discount,
[StringValue("DISCOUNT EARLY-ADOPTER")] DiscountEarlyAdopter,
[StringValue("COMMERCIAL")] Commercial,
[StringValue("COMMERCIAL EARLY-ADOPTER")] CommercialEarlyAdopter
}
Then you can simply do this:
licenseType.GetStringValue();
Convert to string using "G" format, then replace "_" (underscore) with spaces:
LicensceTypes license = LicenseTypes.COMMERCIAL_EARLY_ADOPTERS;
string licenseDescription = license.ToString("G").Replace('_', ' ');
// licenseDescription = "COMMERCIAL EARLY ADOPTERS"
I think I would use a class to avoid this scenario. :/
public class LicenceType
{
private string name;
public LicenceType(string Name)
{
this.name = Name;
}
public override string ToString()
{
return name;
}
}
public static class LicenceTypes
{
public static LicenceType DISCOUNT = new LicenceType("DISCOUNT");
public static LicenceType DISCOUNT_EARLY_ADOPTER= new LicenceType("DISCOUNT EARLY-ADOPTER");
public static LicenceType COMMERCIAL= new LicenceType("COMMERCIAL");
public static LicenceType COMMERCIAL_EARLY_ADOPTER= new LicenceType("COMMERCIAL EARLY-ADOPTER");
}
I'm trying to do this:
public interface IVirtualInterface{ }
public interface IFabricationInfo : IVirtualInterface
{
int Type { get; set; }
int Requirement { get; set; }
}
public interface ICoatingInfo : IVirtualInterface
{
int Type { get; set; }
int Requirement { get; set; }
}
public class FabInfo : IFabricationInfo
{
public int Requirement
{
get { return 1; }
set { }
}
public int Type
{
get {return 1;}
set{}
}
}
public class CoatInfo : ICoatingInfo
{
public int Type
{
get { return 1; }
set { }
}
public int Requirement
{
get { return 1; }
set { }
}
}
public class BusinessObj
{
public T VirtualInterface<T>() where T : IVirtualInterface
{
Type targetInterface = typeof(T);
if (targetInterface.IsAssignableFrom(typeof(IFabricationInfo)))
{
var oFI = new FabInfo();
return (T)oFI;
}
if (targetInterface.IsAssignableFrom(typeof(ICoatingInfo)))
{
var oCI = new CoatInfo();
return (T)oCI;
}
return default(T);
}
}
But getting a compiler error: Canot convert type 'GenericIntf.FabInfo' to T
How do I fix this?
thanks
Sunit
Assuming all IVirtualInterface implementations will have a default constructor (as in your example), you can do this instead:
public T VirtualInterface<T>() where T : IVirtualInterface, new()
{
return new T();
}
Simples!
EDIT:
Exactly what you're trying to achieve is difficult to determine from the code you've posted. Why isn't VirtualInterface static (implies all business objects inherit this method which seems odd)? If you need o be able to parameterised constructors for your IVirtualInterface implementations, where would those parameter values come from (you're not passing any into the VirtualInterface method)?
If you just want to avoid cluttering up intellisense (a poor reason for trying something like this IMHO) but also want to maintain support for parameteried constructors, then how about this:
public T VirtualInterface<T>(Func<T> constructor) where T : IVirtualInterface
{
return constructor();
}
With usage:
IFabricationInfo fabInfo =
new BusinessObj().VirtualInterface<IFabricationInfo>(() => new FabInfo());
Overall though, and without enough information to make a solid judgement, I'd have to say that this smells.
The fact that T and FabInfo both implement IVirtualInterface does not mean you can perform a cast between the two types. For example if T is CoatInfo, then it is not compatible type with FabInfo.
Interfaces allow you to treat different objects as similar types based on the methods they provide. However, this does not mean that you can perform casts between these two types as their actual implementation can vary greatly.
Edit: After re-reading your method again, I see that you are checking the type first. The problem is that the compiler doesn't know you are performing that logic before you try to make that cast. If you are writing a generic method and are checking the type of T, you are likely misusing the concept of generics. See the other answers for the way you should be creating new instances of T.
You can get around this error by first casting to object before casting to T e.g.
return (T)(object)oFI;
and similarly for CoatInfo
However I think switching on a generic type is an abuse, since if you want a limited number of possible return values, you could make the options explicit e.g.
public IFabricationInfo GetFabricationInfo()
{
return new FabInfo();
}
My function returns some long value
which contains two values in lower and higher 32 bits.
I thought the best ways to handle return value
is to derive my custom type from long and provide
type extenders like GetLowerValue(), GetHigherValue().
The problem is that .NET does not allow to derive from long
If you compile that
public class SubmitOrderResult : long
{
}
you get:
cannot derive from sealed type 'long'
Why is that designed so and how can overcome it?
Thanks
As already mentioned value types in .NET are sealed so there is no way you can derive from long. You should create extension methods as suggested.
Example
public static class LongExtensions
{
public static long GetLowerValue(this long value)
{
...
}
public static long GetHigherValue(this long value)
{
...
}
}
You can't derive from any of the .NET Value Types - they are all sealed by definition.
Perhaps you could implement your GetLowerValue and GetHigherValue methods as extension methods?
My function returns some long value which contains two values in lower and higher 32 bits.
That sounds like a really, really dirty hack. It could be appropriate for close-to-metal languages (e.g. C) but not for a higher-level, object-oriented language.
In OO languages, you extend the type system, not harass existing types to do your bidding. Thus, the solution should be to create a new type which carries your information.
What you can do is write a struct with implicit conversion operators. That will work exactly the way you want:
public struct SubmitOrderResult
{
private long _result;
public SubmitOrderResult(long result)
{
_result = result;
}
public long Result
{
get { return _result; }
set { _result = value; }
}
public int GetHigherValue()
{
return (int)(_result >> 32);
}
public int GetLowerValue()
{
return (int)_result;
}
public static implicit operator SubmitOrderResult(long result)
{
return new SubmitOrderResult(result);
}
public static implicit operator long(SubmitOrderResult result)
{
return result._result;
}
}
Then you can do:
SubmitOrderResult result = someObject.TheMethod();
Console.WriteLine(result.GetHigherValue());
Console.WriteLine(result.GetLowerValue());
...just like you wanted.
If I understand correctly, your function actually returns two values, and the fact that you pack them into a long is an implementation detail. In that case, hide this detail and create a class which contains the value and the required operations:
public class SubmitOrderResult
{
private readonly long value_;
public int OneValue
{
get { return (int)(value_ >> 32); }
}
public int TheOtherValue
{
get { return (int)(value_ & 0xFFFFFFFF); }
}
public SubmitOrderResult(long value)
{ value_ = value; }
}
You can't overcome it.
As long is a sealed type and therefore you can't inherit from them. See the MSDN
Because structs are implicitly sealed, they cannot be inherited.
For more information, see Inheritance (C# Programming Guide).