How can I convert an array of string to enum?
The following code gives a basic idea about what is expected,
permission.Permissions.Add(Enum.Parse(typeof(PagePermission) ,a );
however, it throws an error like
can not convert object to enum.
Here, PagePermission is enum.
string pagePermission = "View,Edit";
string[] permissions = pagePermission.Split(',');
permission.Permissions = new List<PagePermission>();
for (int i = 0; i < permissions.Length; i++)
{
string a = permissions[i];
permission.Permissions.Add(Enum.Parse(typeof(PagePermission) ,a );
}
Use this
IEnumerable<myEnum> items = myArray.Select(a => (myEnum)Enum.Parse(typeof(myEnum), a));
Enum.Parse returns an object, you need to cast it to the actual enum type. In your case:
permission.Permissions.Add((PagePermission)Enum.Parse(typeof(PagePermission), a);
Otherwise you'd be adding an object to a list of PagePermission, which causes the error you had.
Related
I'm having some trouble letting a user save his value into an array, here's the code that I tried with:
I want to be able to store up to 4 objects, and then reset them with null, if that is possible.
string [] array = new string[4];
array[i] += Console.ReadLine(); //and now it says: Cannot implicitly convert
type 'string' to 'int'. I also want to reset the value with this code:
array[i] = null;
I'm new to arrays and it's really hard. Thanks in advance!
The problem is in i variable that has a type string instead of int. You need to use integer values for your indexer in array.
Also there is no reason to use += operator. Just assign your value to the array element by using =.
var index = int.Parse(i); // the better way is to use TryParse to check your i string contains integer value
array[index] = Console.ReadLine();
Looks to me like you are trying to index the array using a name. If so, I would use a Dictionary instead:
var key = "MyValueKey"; //I presume this is currently your "i" value
var dict = new Dictionary<String, String>();
var userVal = Console.ReadLine();
if (String.IsNullOrWhitespace(userVal))
userVal = null;
if (dict.ContainsKey(key))
dict[key] = userVal;
else
dict.Add(key, userVal);
I have an object whose value may be one of several array types like int[] or string[], and I want to convert it to a string[]. My first attempt failed:
void Do(object value)
{
if (value.GetType().IsArray)
{
object[] array = (object[])value;
string[] strings = Array.ConvertAll(array, item => item.ToString());
// ...
}
}
with the runtime error Unable to cast object of type 'System.Int32[]' to type 'System.Object[]', which makes sense in retrospect since my int[] doesn't contain boxed integers.
After poking around I arrived at this working version:
void Do(object value)
{
if (value.GetType().IsArray)
{
object[] array = ((Array)value).Cast<object>().ToArray();
string[] strings = Array.ConvertAll(array, item => item.ToString());
// ...
}
}
I guess this is OK, but it seems pretty convoluted. Anyone have a simpler way?
You don't need to convert it to an array and then use LINQ. You can do it in a more streaming fashion, only converting to an array at the end:
var strings = ((IEnumerable) value).Cast<object>()
.Select(x => x == null ? x : x.ToString())
.ToArray();
(Note that this will preserve nulls, rather than throwing an exception. It's also fine for any IEnumerable, not just arrays.)
.ToArray makes multiple memory allocations in most cases, but there are few ways around it:
object value = new[] { 1, 2.3 };
IList list = value as IList;
string[] strings = new string[list.Count];
for (int i = 0; i < strings.Length; i++)
strings[i] = Convert.ToString(list[i]);
In most cases that might be a bit overkill and waste of vertical space, so I would use something like the accepted answer with an optional null-conditional operator ? to check if the source is array:
string[] strings = (value as Array)?.Cast<object>().Select(Convert.ToString).ToArray();
void Do(object value)
{
if (value.GetType().IsArray)
{
string[] strings = ((object[]) value).Select(obj => Convert.ToString(obj)).ToArray();
}
}
I have declared my int[] as follows
int[] iroleID = new int[] { };
My code for getting the values from database and assigning to iroleid is as follows
if (oAuthenticate.getTaskID(out m_oDataSet1, "uspgetTaskID"))
{
for (int iTaskid = 0; iTaskid < m_oDataSet1.Tables[0].Rows.Count; iTaskid++)
{
iroleID = Convert.ToInt32(m_oDataSet1.Tables[0].Rows[iTaskid]["RoleID"].ToString());
strTaskID = m_oDataSet1.Tables[0].Rows[iTaskid]["TaskID"].ToString();
arrTaskID.Add(strTaskID);
}
}
But i am getting an error as mentioned Cannot implicitly convert type 'int' to 'int[]' can any one help me
And no surprise here. Look at
iroleID = Convert.ToInt32(...);
Convert.ToIn32 results in an int just like the compiler claims.
Either do something like:
if (oAuthenticate.getTaskID(out m_oDataSet1, "uspgetTaskID"))
{
var iroleID = new int[m_oDataSet1.Tables[0].Rows.Count];
for (int iTaskid = 0; iTaskid < m_oDataSet1.Tables[0].Rows.Count; iTaskid++)
{
iroleID[iTaskid] = Convert.ToInt32(m_oDataSet1.Tables[0].Rows[iTaskid]["RoleID"].ToString());
/* ... */
}
}
or rethink your algorithm.
PS: I can hardly tell you what exactly to do as you don't show what the purpose of iRoleID is.
off course!
iroleID = Convert.ToInt32(m_oDataSet1.Tables[0].Rows[iTaskid]["RoleID"].ToString());
iroleID is an int array; Convert.ToInt32() returns an int .
so:
-you must declare an int variable tu store Convert.ToInt32() value
or
-just add Convert.ToInt32() result to iroleID ( iroleID.Add(Convert.ToInt32(...)) )
Sure, you can't just assign the int value to the int[] variable. Probably you need to add items to the collection. Change your int[] iroleID = new int[] { }; to List<int> iroleID = new List<int>(); and then change code to:
if (oAuthenticate.getTaskID(out m_oDataSet1, "uspgetTaskID"))
{
for (int iTaskid = 0; iTaskid < m_oDataSet1.Tables[0].Rows.Count; iTaskid++)
{
iroleID.Add(Convert.ToInt32(m_oDataSet1.Tables[0].Rows[iTaskid]["RoleID"].ToString()));
strTaskID = m_oDataSet1.Tables[0].Rows[iTaskid]["TaskID"].ToString();
arrTaskID.Add(strTaskID);
}
}
iroleID = Convert.ToInt32(m_oDataSet1.Tables[0].Rows[iTaskid]["RoleID"].ToString());
This would convert the RoleID columns value to an integer. You are taking this integer and trying to assign it to an integer array which of course is not possible. What exactly is your idea? If it is to populate a single array with all the IDs you can do the same as you did but assign it to a normal integer and then add that integer to a list or something.
You can also just use plain ADO.NET to retrieve all the values from that column and cast it to an List. That would be better.
One problem has already been answered, you must add it to an array giving the position you want
iroleID[iTaskid] = Convert.ToInt32(m_oDataSet1.Tables[0].Rows[iTaskid]["RoleID"].ToString());
the other problem is, that you create an array. You must give the length of the array.
int[] iroleID = new int[m_oDataSet1.Tables[0].Rows.Count];
Use indexing for the int array to assign a value, you can't assign an integer directly to an integer array.
iroleID[0] = Convert.ToInt32(m_oDataSet1.Tables[0].Rows[iTaskid]["RoleID"].ToString());
Consider string.Format() whose parameters are a string and, among others in the overload list, an object[] or many objects.
This statement succeeds:
string foo = string.Format("{0} {1}", 5, 6);
as does this:
object[] myObjs = new object[] {8,9};
string baz = string.Format("{0} and {1}", myObjs;
as does an array of strings:
string[] myStrings = new string[] {"abc", "xyz"};
string baz = string.Format("{0} {1}", myStrings);
It seems that the integers, when specified individually, can be boxed or coerced to type object, which in turn is coerced to a string.
This statement fails at runtime.
int[] myInts = new int[] {8,9};
string bar = string.Format("{0} and {1}", myInts);
Index (zero based) must be greater than or equal to zero and less than the size of the argument list.
Why doesn't or can't the int array be coerced or boxed to an object[] or string[]?
Out of a small bit of curiosity, why doesn't the compiler catch this?
The call fails with the same reason the following will also fail:
string foo = string.Format("{0} {1}", 5);
You are specifying two arguments in the format but only specifying one object.
The compiler does not catch it because int[] is passed as an object which is a perfectly valid argument for the function.
Also note that array covariance does not work with value types so you cannot do:
object[] myInts = new int[] {8,9};
However you can get away with:
object[] myInts = new string[] { "8", "9" };
string bar = string.Format("{0} {1}", myInts);
which would work because you would be using the String.Format overload that accepts an object[].
Your call gets translated into this:
string foo = string.Format("{0} {1}", myInts.ToString());
which results in this string:
string foo = "System.Int32[] {1}";
So as the {1} doesn't have a parameter, it throws an exception
I think the concept you are having an issue with is why int[] isn't cast to object[]. Here's an example that shows why that would be bad
int[] myInts = new int[]{8,9};
object[] myObjs = (object[])myInts;
myObjs[0] = new object();
The problem is that we just added an object into a int array.
So what happens in your code is that myInts is cast to object and you don't have a second argument to fill in the {1}
Short way to make it work (not the most optimal though):
int[] myInts = new int[] { 8, 9 };
string[] myStrings = Array.ConvertAll(myInts, x => x.ToString());
// or using LINQ
// string[] myStrings = myInts.Select(x => x.ToString()).ToArray();
bar = string.Format("{0} and {1}", myStrings);
This is quite an old question, but I recently got the same issue. And I haven't seen an answer that works for me, so I'll share the solution I found.
Why doesn't or can't the int array be coerced or boxed to an object[] or string[]? Why it isn't boxed, I don't know. But it can be boxed explicitly, see solution below.
Why doesn't the compiler catch this? Because the compiler misinterprets the situation: The type isn't exactly an object array, so it doesn't know what to do with it and decides to perform a .ToString() on the int array, which returns one single parameter containing the type name rather than the parameter list itself. It doesn't do that with a string array, because the target type is already a string - but with any other kind of array the same issue happens (for example bool[]). Consider var arr1 = new int[]{1,2}; with string.Format("{0}", arr1): As long as you have only {0} in the format string, you get only the type name "System.Int32[]" back (and no exception occurs). If you have more placeholders, e.g. string.Format("{0}{1}", arr1), then the exception occurs - because arr1 is misinterpreted as one parameter - and for the compiler, a 2nd one is missing. But what I think is a conceptional bug is that you can't convert arr1, i.e. if you try to do (object[])arr1- you're getting:
CS0030 Cannot convert type 'int[]' to 'object[]'
Solution:
Filling in each element of the int array is not a solution that works for me, because in my project I am creating a format template string dynamically during runtime containing the {0}...{n} - hence I need to pass an array to String.Format.
So I found the following workaround. I created a generic helper function (which of course could be an extension method too if you prefer):
// converts any array to object[] and avoids FormatException
object[] Convert<T>(T[] arr)
{
var obj = new List<object>();
foreach (var item in arr)
{
obj.Add((object)item);
}
return obj.ToArray();
}
Now if you try that in the example below which is showing up the FormatException:
// FormatException: Index (zero based) must be greater than or equal to zero
// and less than the size of the argument list
var arr1 = (new int[] { 1, 2 });
string.Format("{0}{1}{0}{1}", arr1).Dump();
Fix: Use Convert(arr1) as 2nd parameter for string.Format(...) as shown below:
// Workaround: This shows 1212, as expected
var arr1 = (new int[] { 1, 2 });
string.Format("{0}{1}{0}{1}", Convert(arr1)).Dump();
Try example as DotNetFiddle
Conclusion:
As it seems, the .NET runtime really misinterprets the parameter by applying a .ToString() to it, if it is not already of type object[]. The Convert method gives the runtime no other choice than to do it the right way, because it returns the expected type. I found that an explicit type conversion did not work, hence the helper function was needed.
Note: If you invoke the method many times in a loop and you're concerned about speed, you could also convert everything to a string array which is probably most efficient:
// converts any array to string[] and avoids FormatException
string[] ConvertStr<T>(T[] arr)
{
var strArr = new string[arr.Length];
for (int i = 0; i < arr.Length; i++)
{
strArr[i]=arr[i].ToString();
}
return strArr;
}
This is working as well. To convert from a different datatype, such as a dictionary, you can simply use
string[] Convert<K,V>(Dictionary<K,V> coll)
{
return ConvertStr<V>(coll.Values.ToArray());
}
Update: With string interpolation, another short way to solve it is:
var baz = string.Format("{0} and {1}", myInts.Select(s => $"{s}").ToArray());
Your string.Format is expecting 2 arguments ({0} and {1}). You are only supplying 1 argument (the int[]). You need something more like this:
string bar = string.Format("{0} and {1}", myInts[0], myInts[1]);
The compiler does not notice the problem because the format string is evaluated at runtime. IE The compiler doesn't know that {0} and {1} mean there should be 2 arguments.
This works:
string bar = string.Format("{0} and {1}", myInts[0], myInts[1]);
The compiler doesn't catch it because it doesn't evaluate your format string.
The example you gave up top doesn't match what you're trying to do down below... you provided two {} and two arguments, but in the bottom one you only provided one argument.
This is my function.
public Dictionary<string, string> ArrayToDictionaryConverter(object [] objArray)
{
string[] strArray = new string[objArray.Length];
strArray =(string[])objArray;
Dictionary<string, string> dictionary = null;
try
{
dictionary = new Dictionary<string, string>();
for (int iVal = 0; iVal < strArray.Length; )
{
dictionary.Add(strArray[iVal], strArray[iVal + 1]);
iVal += 2;
}
}
catch (Exception ex)
{
}
return dictionary;
}
Getting error :
Unable to cast object of type 'System.Object[]' to type 'System.String[]'.
Why ? is this wrong convention / Casting?
You can't cast an expression to a particular type if it's not actually of that type, or a compatible one (or there's an explicit conversion).
In this case, the array wasn't a string[] - it was an object[]. It could have been a string[], which is why the compiler allowed you to write the cast in the first place - but at execution time the CLR found that it was just an object[].
Do you expect every element in the array to already be a string? If so, you should just cast each element individually. If not, you'll have to add a call to ToString (or some other way of converting each element to a string) - but be careful of null values.
As an aside, empty catch blocks are a really bad idea. What do you really want to happen if something goes wrong? And what kind of errors do you want to handle in what way? Some errors to think about:
What if one of the keys is null?
What if you get duplicate keys?
What if the input array has an odd number of elements?
Finally, I'd suggest putting the i += 2 in the for loop "header" instead of at the end of the block.
Try the Array.ConvertAll method.
See This is working:
public Dictionary ArrayToDictionaryConverter(object [] objArray)
{
string[] strArray = Array.ConvertAll(objArray,Convert.ToString);
Dictionary dictionary = null;
try
{
dictionary = new Dictionary();
for (int iVal = 0; iVal < strArray.Length; )
{
dictionary.Add(strArray[iVal], strArray[iVal + 1]);
iVal += 2;
}
}
catch (Exception ex)
{
}
return dictionary;
}