Related
Please refer the below enums
public enum Fruit
{
Apple = 1,
Orange = 2,
Banana= 3
}
public enum Color
{
Orange = 1,
Yellow = 2,
Red= 3
}
Now I want to map Fruit with Color.So I implemented
public enum FruitColor
{
1= 3,
2= 1,
3= 2
}
I am getting an syntax error when I implement FruitColor
Identifier Expected
How to resolve this?
There is no point in using an enum to map enum values. I would use a dictionary:
Dictionary<Fruit, Color> FruitToColor = new Dictionary<Fruit, Color>
{ { Fruit.Apple, Color.Red }
, { Fruit.Orange, Color.Orange }
, { Fruit.Banana, Color.Yellow }
};
Color colorOfBanana = FruitToColor[Fruit.Banana]; // yields Color.Yellow
Also just putting it out there because I can, the only advantage is you can encode other data in a custom attribute. However, I'd go with the dictionary or a switch ;)
Given
public enum MyFruit
{
[MyFunky(MyColor.Orange)]
Apple = 1,
[MyFunky(MyColor.Yellow)]
Orange = 2,
[MyFunky(MyColor.Red)]
Banana = 3
}
public enum MyColor
{
Orange = 1,
Yellow = 2,
Red = 3
}
public static class MyExteions
{
public static MyColor GetColor(this MyFruit fruit)
{
var type = fruit.GetType();
var memInfo = type.GetMember(fruit.ToString());
var attributes = memInfo[0].GetCustomAttributes(typeof (MyFunkyAttribute), false);
if (attributes.Length > 0)
return ((MyFunkyAttribute)attributes[0]).Color;
throw new InvalidOperationException("blah");
}
}
public class MyFunkyAttribute : Attribute
{
public MyFunkyAttribute(MyColor color) { Color = color;}
public MyColor Color { get; protected set; }
}
Usage
var someFruit = MyFruit.Apple;
var itsColor = someFruit.GetColor();
Console.WriteLine("Fruit = " + someFruit + ", Color = " + itsColor);
Output
Fruit = Apple, Color = Orange
Full Demo Here
You can't have numbers as enum keys. You could use a dictionary to map the values:
var map = new Dictionary<Fruit, Color>
{
{ Fruit.Apple, Color.Red },
{ Fruit.Orange, Color.Orange },
{ Fruit.Banana, Color.Yellow }
};
To access the mapped values use:
var mappedValue = map[Fruit.Apple];
Alternatively, because you want to map the inverse value (1 to 3 and 3 to 1) you could use casts from an integer, although this could be dangerous because the result could be undefined.
var src = (int) Fruit.Apple; // src = 1;
var tar = 4 - src; // tar = 3;
var mapped = (Color) tar;
More generic example:
function Color Map(Fruit fruit)
{
var src = (int) fruit;
var tar = 4 - src;
var color = (Color) tar;
return color;
}
Member identifiers are not allowed to begin with numeric values, you can however use a method to get the proper values from each enum:
public Fruit GetFruit(this Color c) {
switch ((int)c) {
case 1: return (Fruit)3;
case 2: return (Fruit)2;
case 3: return (Fruit)1;
}
return 0;
}
The reverse of this method would give you the Color from the Fruit. You can call this method via the Color type as a static method:
Fruit myFruit = Color.GetFruit(Color.Orange);
I understand that you can configure C# enum flags in this way:
[Flags]
public enum MyEnum
{
Unknown = 0,
Type1 = 1,
Type2 = 2,
Type3 = 4,
Type4 = 8,
Type5 = 16
}
And once this is configured, you can represent a set of enumberations like so:
MyEnum enumerationSet = MyEnum.Type1 | MyEnum.Type2
Then you can make checks against this set, such as:
if(enumerationSet.HasFlag(MyEnum.Type1))
{
// Do something
}
Or print their values, like so:
Console.WriteLine("{0}", enumerationSet);
Which would print:
Type1, Type2
However, can I go in reverse order? For instance, if I know that
MyEnum.Type1 | MyEnum.Type2 == 3
Can I then ask MyEnum what set of its value/types would equal 3? Then, I can create an extension method (GetSet) to execute like this:
List<MyEnum> myEnumSetList = MyEnum.GetSet(3)
Returning either a MyEnum set or a set of values, i.e. {1, 2}.
Please advise.
EDIT: I was able to finally figure it out. Posted my answer below.
You can parse it manually with this code:
var res = 3;
var myEnumSetList = res.ToString()
.Split(new[] { ", " }, StringSplitOptions.None)
.Select(v => (MyEnum)Enum.Parse(typeof(MyEnum), v)).ToList();
If you want a list of flags you can use this:
var f = 1 + 4 + 8;
var s = Convert.ToString(f, 2);
var flags =
s.Where(w=> w !='0').Select(
(c, i) =>
(MyEnum)Enum.Parse(typeof(MyEnum),
(int.Parse(c.ToString())*Math.Pow(2, i)).ToString(CultureInfo.InvariantCulture)));
You can just cast the Integer to an Enum and use an & comparison.
example
var num = 1;
var doesExist = (((enumerationSet) & ((MyEnum) num)) != 0);
Then if it exists you can return it in your extension method.
Full Code
var enumList = new List<MyEnum>();
var testNumbers = new List<int>{ 1, 2, 4};
MyEnum enumerationSet = MyEnum.Type1 | MyEnum.Type2;
foreach (var num in testNumbers)
{
var doesExist = (((enumerationSet) & ((MyEnum) num)) != 0);
if (doesExist)
enumList.Add((MyEnum)num);
}
enumList.ForEach(x => Console.WriteLine(x.ToString()));
return enumList;
After some hacking around, I was able to resolve a list of enum values, based on the value of that respective set OR'ed:
protected List<MyEnum> GetEnumSet(int flagNumber)
{
List<MyEnum> resultList= new List<MyEnum>();
foreach (MyEnum value in Enum.GetValues(typeof(MyEnum)))
{
if (((MyEnum)flagNumber).HasFlag(value))
{
resultList.Add(value);
}
}
return resultList;
}
Here, flagNumber is the value of a respective list OR'ed, i.e. MyEnum.Type1 | MyEnum.Type2. Thus, by sending this method the flagNumber, I get the list { MyEnum.Type1, MyEnum.Type2 }
What are all the array initialization syntaxes that are possible with C#?
These are the current declaration and initialization methods for a simple array.
string[] array = new string[2]; // creates array of length 2, default values
string[] array = new string[] { "A", "B" }; // creates populated array of length 2
string[] array = { "A" , "B" }; // creates populated array of length 2
string[] array = new[] { "A", "B" }; // created populated array of length 2
Note that other techniques of obtaining arrays exist, such as the Linq ToArray() extensions on IEnumerable<T>.
Also note that in the declarations above, the first two could replace the string[] on the left with var (C# 3+), as the information on the right is enough to infer the proper type. The third line must be written as displayed, as array initialization syntax alone is not enough to satisfy the compiler's demands. The fourth could also use inference. So if you're into the whole brevity thing, the above could be written as
var array = new string[2]; // creates array of length 2, default values
var array = new string[] { "A", "B" }; // creates populated array of length 2
string[] array = { "A" , "B" }; // creates populated array of length 2
var array = new[] { "A", "B" }; // created populated array of length 2
The array creation syntaxes in C# that are expressions are:
new int[3]
new int[3] { 10, 20, 30 }
new int[] { 10, 20, 30 }
new[] { 10, 20, 30 }
In the first one, the size may be any non-negative integral value and the array elements are initialized to the default values.
In the second one, the size must be a constant and the number of elements given must match. There must be an implicit conversion from the given elements to the given array element type.
In the third one, the elements must be implicitly convertible to the element type, and the size is determined from the number of elements given.
In the fourth one the type of the array element is inferred by computing the best type, if there is one, of all the given elements that have types. All the elements must be implicitly convertible to that type. The size is determined from the number of elements given. This syntax was introduced in C# 3.0.
There is also a syntax which may only be used in a declaration:
int[] x = { 10, 20, 30 };
The elements must be implicitly convertible to the element type. The size is determined from the number of elements given.
there isn't an all-in-one guide
I refer you to C# 4.0 specification, section 7.6.10.4 "Array Creation Expressions".
Non-empty arrays
var data0 = new int[3]
var data1 = new int[3] { 1, 2, 3 }
var data2 = new int[] { 1, 2, 3 }
var data3 = new[] { 1, 2, 3 }
var data4 = { 1, 2, 3 } is not compilable. Use int[] data5 = { 1, 2, 3 } instead.
Empty arrays
var data6 = new int[0]
var data7 = new int[] { }
var data8 = new [] { } and int[] data9 = new [] { } are not compilable.
var data10 = { } is not compilable. Use int[] data11 = { } instead.
As an argument of a method
Only expressions that can be assigned with the var keyword can be passed as arguments.
Foo(new int[2])
Foo(new int[2] { 1, 2 })
Foo(new int[] { 1, 2 })
Foo(new[] { 1, 2 })
Foo({ 1, 2 }) is not compilable
Foo(new int[0])
Foo(new int[] { })
Foo({}) is not compilable
Enumerable.Repeat(String.Empty, count).ToArray()
Will create array of empty strings repeated 'count' times. In case you want to initialize array with same yet special default element value. Careful with reference types, all elements will refer same object.
In case you want to initialize a fixed array of pre-initialized equal (non-null or other than default) elements, use this:
var array = Enumerable.Repeat(string.Empty, 37).ToArray();
Also please take part in this discussion.
var contacts = new[]
{
new
{
Name = " Eugene Zabokritski",
PhoneNumbers = new[] { "206-555-0108", "425-555-0001" }
},
new
{
Name = " Hanying Feng",
PhoneNumbers = new[] { "650-555-0199" }
}
};
Example to create an array of a custom class
Below is the class definition.
public class DummyUser
{
public string email { get; set; }
public string language { get; set; }
}
This is how you can initialize the array:
private DummyUser[] arrDummyUser = new DummyUser[]
{
new DummyUser{
email = "abc.xyz#email.com",
language = "English"
},
new DummyUser{
email = "def#email.com",
language = "Spanish"
}
};
Just a note
The following arrays:
string[] array = new string[2];
string[] array2 = new string[] { "A", "B" };
string[] array3 = { "A" , "B" };
string[] array4 = new[] { "A", "B" };
Will be compiled to:
string[] array = new string[2];
string[] array2 = new string[] { "A", "B" };
string[] array3 = new string[] { "A", "B" };
string[] array4 = new string[] { "A", "B" };
Repeat without LINQ:
float[] floats = System.Array.ConvertAll(new float[16], v => 1.0f);
int[] array = new int[4];
array[0] = 10;
array[1] = 20;
array[2] = 30;
or
string[] week = new string[] {"Sunday","Monday","Tuesday"};
or
string[] array = { "Sunday" , "Monday" };
and in multi dimensional array
Dim i, j As Integer
Dim strArr(1, 2) As String
strArr(0, 0) = "First (0,0)"
strArr(0, 1) = "Second (0,1)"
strArr(1, 0) = "Third (1,0)"
strArr(1, 1) = "Fourth (1,1)"
For Class initialization:
var page1 = new Class1();
var page2 = new Class2();
var pages = new UIViewController[] { page1, page2 };
Another way of creating and initializing an array of objects. This is similar to the example which #Amol has posted above, except this one uses constructors. A dash of polymorphism sprinkled in, I couldn't resist.
IUser[] userArray = new IUser[]
{
new DummyUser("abc#cde.edu", "Gibberish"),
new SmartyUser("pga#lna.it", "Italian", "Engineer")
};
Classes for context:
interface IUser
{
string EMail { get; } // immutable, so get only an no set
string Language { get; }
}
public class DummyUser : IUser
{
public DummyUser(string email, string language)
{
m_email = email;
m_language = language;
}
private string m_email;
public string EMail
{
get { return m_email; }
}
private string m_language;
public string Language
{
get { return m_language; }
}
}
public class SmartyUser : IUser
{
public SmartyUser(string email, string language, string occupation)
{
m_email = email;
m_language = language;
m_occupation = occupation;
}
private string m_email;
public string EMail
{
get { return m_email; }
}
private string m_language;
public string Language
{
get { return m_language; }
}
private string m_occupation;
}
For the class below:
public class Page
{
private string data;
public Page()
{
}
public Page(string data)
{
this.Data = data;
}
public string Data
{
get
{
return this.data;
}
set
{
this.data = value;
}
}
}
you can initialize the array of above object as below.
Pages = new Page[] { new Page("a string") };
Hope this helps.
hi just to add another way:
from this page :
https://learn.microsoft.com/it-it/dotnet/api/system.linq.enumerable.range?view=netcore-3.1
you can use this form If you want to Generates a sequence of integral numbers within a specified range strat 0 to 9:
using System.Linq
.....
public int[] arrayName = Enumerable.Range(0, 9).ToArray();
You can also create dynamic arrays i.e. you can first ask the size of the array from the user before creating it.
Console.Write("Enter size of array");
int n = Convert.ToInt16(Console.ReadLine());
int[] dynamicSizedArray= new int[n]; // Here we have created an array of size n
Console.WriteLine("Input Elements");
for(int i=0;i<n;i++)
{
dynamicSizedArray[i] = Convert.ToInt32(Console.ReadLine());
}
Console.WriteLine("Elements of array are :");
foreach (int i in dynamicSizedArray)
{
Console.WriteLine(i);
}
Console.ReadKey();
Trivial solution with expressions. Note that with NewArrayInit you can create just one-dimensional array.
NewArrayExpression expr = Expression.NewArrayInit(typeof(int), new[] { Expression.Constant(2), Expression.Constant(3) });
int[] array = Expression.Lambda<Func<int[]>>(expr).Compile()(); // compile and call callback
To initialize an empty array, it should be Array.Empty<T>() in dotnet 5.0
For string
var items = Array.Empty<string>();
For number
var items = Array.Empty<int>();
Another way is by calling a static function (for a static object) or any function for instance objects. This can be used for member initialisation.
Now I've not tested all of this so I'll put what I've tested (static member and static function)
Class x {
private static Option[] options = GetOptionList();
private static Option[] GetOptionList() {
return (someSourceOfData).Select(dataitem => new Option()
{field=dataitem.value,field2=dataitem.othervalue});
}
}
What I'd love to know is if there is a way to bypass the function declaration. I know in this example it could be used directly, but assume the function is a little more complex and can't be reduced to a single expression.
I imagine something like the following (but it doesn't work)
Class x {
private static Option[] options = () => {
Lots of prep stuff here that means we can not just use the next line
return (someSourceOfData).Select(dataitem => new Option()
{field=dataitem.value,field2=dataitem.othervalue});
}
}
Basically a way of just declaring the function for the scope of filling the variable.
I'd love it if someone can show me how to do that.
For multi-dimensional array in C# declaration & assign values.
public class Program
{
static void Main()
{
char[][] charArr = new char[][] { new char[] { 'a', 'b' }, new char[] { 'c', 'd' } };
int[][] intArr = new int[][] { new int[] { 1, 2 }, new int[] { 3, 4 } };
}
}
I have a string "hello", and a integer 1.
I want to convert them into
new { hello= 1 }
dynamically, and without using any condition like
switch(p1){
case "hello":
return new {hello=p2};
}
as there is many different string and I need to put many items into a super object set like
var emotion = {smile=1,angry=2,worry=3}
the problem is smile, angry and worry was string. but after added to emotion, they are not string, but just an index (like dictionary, however dictionary's index also has dataType, which is not my expected result)
Is it possible?
--- Updated --- i have added a function to specify the expected output.
private void Question_1()
{
//i have
string a = "hello";
int b = 1;
// i want to convert a and b to new {a = b} programmatically, for example i can convert a and b to a Tuple like
Tuple<string, int> x = new Tuple<string, int>(a,b);
//but i dont know how to to convert it to new {a = b}, as i need to put the string "hello" as key to new {a=b}
var result = new { hello = b }; //you can see i can put b after =, but i can never put the string hello at the left
}
private void Question_2()
{
//and the final should be like this
List<Tuple<string, int>> list = new List<Tuple<string, int>>() {
new Tuple<string,int>("smile",1),
new Tuple<string,int>("cry",2),
new Tuple<string,int>("worry",3)
};
foreach (Tuple<string, int> item in list)
{
//adding item's string and int into result and finally the result is
}
//the final result
var finalResult = new { smile = 1, cry = 2, worry = 3 };
}
Use .NET naming conventions for enums: They should be Pascal Notation.
enum Emotion
{
Smile = 1, Angry = 2, Worry = 3
}
var l = new List<Emotion> { Emotion.Angry, Emotion.Smile, Emotion.Worry };
You can also use a friendly name for your enum with the DesriptionAttribute like this:
enum Emotion
{
[Description("Smiling")]
Smile = 1,
[Description("Angry Type")]
Angry = 2,
[Description("Worry Type")]
Worry = 3
}
Any reason you can't just use a dictionary?
var hi = new Dictionary<string,int>();
hi[p1] = p2;
return hi; // Would serialize the same way as your anonymous object
If not, then you could use the expando object to dynamically set properties at runtime.
var hi = new ExpandoObject() as IDictionary<string, object>;
hi.Add(p1, p2);
var p2Value = (int)((dynamic)hi).hello;
You can use ExpandoObject.
class Program
{
static dynamic obj = new ExpandoObject();
static void Main(string[] args)
{
AddProperty("City", "Sydney");
AddProperty("Country", "Australia");
AddProperty("hello", 1);
Console.WriteLine(obj.City);
Console.WriteLine(obj.Country);
Console.WriteLine(obj.hello);
//We can even use dynamic property names ( e.g. cityProp in below example )
IDictionary<string, object> dic = obj as IDictionary<string, object>;
Console.WriteLine("City is : " + dic[cityProp]);
}
public static void AddProperty(string propertyName, object value)
{
IDictionary<string, object> a = obj as IDictionary<string, object>;
a[propertyName] = value;
}
}
dynamic emotion = new { smile = 1, angry = 2, worry = 3 };
Console.WriteLine(emotion.smile);
Like this?
Edit: Based on your comment on another answer:
it is not worked, i need it able to be accepted by
Url.Action("action","controller", x), where x is thing that i'm trying
to create dynamically . i don't know if dynamic too complex or what.
but Url.Action dont know how to read it
There's obviously more to the question than just C#, clearly this an MVC question. You should really add as much information as you can about what you need.
Your answer is probably here:
https://stackoverflow.com/a/15112223/1685167
The #Url.Action() method is proccess on the server side, so you cannot
pass a client side value to this function as a parameter.
I've got a JArray that represents the json substring [1,2,3]. I'd like to turn it into an int[] instead.
What's the correct way of doing this? The best way I've found so far is to do the following:
int[] items = new int[myJArray.Count];
int i = 0;
foreach (int item in myJArray)
{
items[i++] = item;
}
myJArray.ToObject<int[]>();
You can also specify HashSet, List etc.
The accepted answer relies on .NET's conversion - this technique uses JSON.NET's own in addition to what .NET can provide so works with more scenarios.
It's also faster as it isn't using a generator & closure for the LINQ operation.
int[] items = myJArray.Select(jv => (int)jv).ToArray();
A cast needed first for me:
((Newtonsoft.Json.Linq.JArray)myJArray).Select(item => (int)item).ToArray()
This is pretty weak because you have to convert back into a string, but if you are doing something quick and dirty, where the performance hit won't matter, I use the below method. I like it because I don't have to write any code to map properties between json/JObject and my POCO's.
public static class JsonExtensions {
public static T As<T>(this JObject jobj) {
return JsonConvert.DeserializeObject<T>(JsonConvert.SerializeObject(jobj));
}
public static List<T> ToList<T>(this JArray jarray) {
return JsonConvert.DeserializeObject<List<T>>(JsonConvert.SerializeObject(jarray));
}
}
[Test]
public void TestDeserializeRootObject() {
var json = #"{ id: 1, name: ""Dwight"" }";
var jfoo = JsonConvert.DeserializeObject(json);
var foo = (jfoo as JObject).As<Foo>();
Assert.AreEqual(1, foo.Id);
Assert.AreEqual("Dwight", foo.Name);
}
[Test]
public void TestDeserializeArray() {
var json = #"[
{ id: 1, name: ""Dwight"" }
, { id: 2, name: ""Pam"" }
]";
var foosArr = JsonConvert.DeserializeObject(json);
Assert.IsInstanceOf<JArray>(foosArr);
Assert.AreEqual(2, (foosArr as JArray).Count);
var foos = (foosArr as JArray).ToList<Foo>();
Assert.AreEqual(2, foos.Count);
var foosDict = foos.ToDictionary(f => f.Name, f => f);
Assert.IsTrue(foosDict.ContainsKey("Dwight"));
var dwight = foosDict["Dwight"];
Assert.AreEqual(1, dwight.Id);
Assert.AreEqual("Dwight", dwight.Name);
Assert.IsTrue(foosDict.ContainsKey("Pam"));
var pam = foosDict["Pam"];
Assert.AreEqual(2, pam.Id);
Assert.AreEqual("Pam", pam.Name);
}
int[] items = new int[myJArray.Count];
for (int i=0; i < myJArray.Count;i++)
{
items[i] = (int)myJArray[i]
}
this is the fastes solution you can do. The classic for is a bit faster than the ForEach as you access the item by the index(the foreach behind the scene uses the IEnumerator interface)
or if you prefer:
JsonArray arr = JsonConvert.Import("[1,2,3,4]");
int[] nums = (int[]) arr.ToArray(typeof(int));