I'm using Xamarin.iOS. How can I convert UICollectionElementKindSection.Header to NSString?
Error CS1503: Argument #1' cannot convertUIKit.UICollectionElementKindSection' expression to type `Foundation.NSString' (CS1503)
I tried the following:
UICollectionElementKindSection.Header.ToString();
(NSString)UICollectionElementKindSection.Header;
(string)UICollectionElementKindSection.Header;
Everytime I get a build error.
For type-safety UICollectionElementKindSectionHeader (and other values) are mapped to an enum, UICollectionElementKindSectionKey. That makes code completion a lot easier (in the IDE) and remove potential typos/mistakes in code.
Turning the enum values into a string (and then an NSString) is possible - but that won't create the same NSString constant that ObjC applications used (even less since, sometime, Apple uses pointers, not string content, for constant comparison).
If you need to use an API that does not use the enum but needs that constant you can do:
IntPtr uikit = Dlfcn.dlopen (Constants.UIKitLibrary, 0);
NSString header = Dlfcn.GetStringConstant (uikit, "UICollectionElementKindSectionHeader");
Note: if that's an API part of Xamarin.iOS.dll then please let us know. We'll either expose the constant or provide an overload that accept the enum.
(NSString)UICollectionElementKindSection.Header.ToString() throws no build error anymore. My app still doesn't work but it's for another reason.
Related
Expression selector = expression.ConvertToSelector();
Type _returnType = expression.returnType;
var genericExpression = selector as Expression<Func<TEntity, _returnType>>;
I am trying to pass the type but cant find a way of doing it efficently. Is there any easy way of doing it?
Error Image:
This is not possible and to understand why, you need to look into what generic types are and what happens on build. Generics are compile time feature. Meaning whatever it does, it does at time of compiling (before you run application). Behind the scenes, .Net will create classes and instructions based on your code.
In the sample you have shown, the variable is a runtime entity. Compiler does not know what to do with it since the variable does not exist at compile time.
If you know the return type of your variable while writing code, you that Type instead or if the return types could be multiple, explore inheritance or interfacing if that could be used.
In general, with any compile time feature ask this: Do I know all the types which this piece of code uses? And is there any place where my answer is "oh it could be type A or B or C which cannot be base classed or interfaced*"? Unless your answers are yes and no, there is very little chance this code will compile.
*Is that even a word?
I'm using Pythonnet 2.4.0 to access a C# dll. I have a Windows 10 machine with Python 3.7.6.
I'm trying to use a method that only takes a path string as argument, but I don't manage to make it work.
import clr
sys.path.append(os.getcwd)
clr.AddReference('C#Wrapper')
path = "C:\\Users\\Username\\Folder"
c#class.method(string path)
If I use the overloads attribute from pythonnet, it tells me that the argument should be of type System.String, however doing something like below didn't help either:
path = System.String("C:\\Users\\Username\\Folder")
I keep getting a TypeError: No Method matches given arguments.
Do I need to encode the string or make a char array in order for c# to be able to understand it?
Edit:
I've just found a test function in the dll that only takes an Int32 argument and I have the same problem! I tried things like:
import ctypes
c#class.testmethod(ctypes.c_int32(1))
from System import Int32
c#class.testmethod(Int32(1))
but nothing worked. How can I pass arguments to the c# dll?
[Solved]:
I figured it out myself. In the second case I simply forgot to instantiate a class object. I should have done:
classobj = c#class()
classobj.testmethod(1)
This made me realize that in the first case I had basically the same issue. I followed a Visual Basic manual to write my Python program where it said something like this:
classobj = c#class
However in Python you need to write:
classobj = c#class()
So the missing parenthesis was causing the TypeError: No Method matches given arguments, which was very misleading. The type conversion and passing of arguments is perfectly handled thanks to the amazing developers of phythonnet! I won't delete this question in case other people experience the same issue.
The answer above is correct: Pythonnet passing arguments to c# dll.
I'd just like clarify what it means.
The error occurred because a method from a class was accessed without instantiating the object.
The solution is one of the two:
create an instance of the class
mark the .net method as static
The problem was that the error message is misleading, it says "No method matches given arguments". Which made me try to find the right argument.
By me this occurred when I forgot to add the static modifier to the .net method I called.
What are the benefits of using a custom enumeration like Direction over built-in types like System.Byte or String?
This question is asked in Mumbai University for "B.Sc.IT" (ASP.NET With C#) Course in the year - may/2018. I'm not gettin' correct answer. Please help me anyone, who the know the correct answers for this question.
I think what this question is getting at is that an enumeration has a predefined set of values, so things like typos are caught by the compiler. For example:
public enum Direction{
Up, Down, Left, Right
}
It's impossible to define a Direction as Diagonal, the compiler won't let you. You also get intelli sense from enums:
Strings/Bytes do not have a well defined list of values. This is summed up nicely by the meme stringly typing:
Method parameters that take strings when other more appropriate types
should be used. On the occasion that a string is required in a method
call (e.g. network service), the string is then passed and used
throughout the rest of the call graph without first converting it to a
more suitable internal representation (e.g. parse it and create an
enum, then you have strong typing throughout the rest of your
codebase). Message passing without using typed messages etc.
Excessively stringly typed code is usually a pain to understand and
detonates at runtime with errors that the compiler would normally
find.
So you don't end up with data like
N
n
North
Nor.
N.
Nord
When you were expecting a compass direction. Using a string instead of an Enum or at least a constraint of some sort will make queries and reports a huge annoyance for everybody that comes after you, forever.
I have asked How can I get the number of enums as a constant?, and I found out that I cannot get the count of enums during compile time, because C# uses reflection to do so.
I read What is reflection and why is it useful?, so I have a very basic understanding of reflection.
To get the count of enums, I can use Enum.GetNames(typeof(Item.Type)).Length;, and this happens during runtime using reflection.
I don't see any runtime knowledge needed to get the count of enums, because as far as I know, the count of enums cannot be changed during runtime.
Why does C# have to use reflection to get the count of enums? Why can't it do so during compile time?
Just because something can be evaluated at compile time doesn't mean that someone has programmed the compiler to do so. string.Format("{0:N2}", Math.PI) is another example.
The only way at present to get the count of the number of values of an Enum is by using reflection (Enum.GetNames or something similar). So it is not a constant expression, although technically the compiler could just evaluate the expression at compile-time and determine what the result is.
nameof is a perfect example. It is constant at compile-time, but there was no mechanism to extract the result at compile time until someone designed, developed, tested, documented, and shipped the feature. None of those are free, and thus the idea must compete for valuable resources (people, time, money) against other features that may be more valuable.
So if you feel that a compile-time construct like enumcount(Item.Type) is a valuable addition to the language, then you are more than welcome to post a suggestion on Connect and see if it makes it to the top of the feature list.
But, I need this number as a constant number, so that I can use it in Unity's [Range(int, int)] feature.
One non-ideal workaround is to define a constant that matches the current number of enum items, and throw an exception at run-time if the counts do not match:
Define a public constant right next to your enum, commenting it so that developers know to update it:
// Update this value any time the Type enum is updated
public const int TypeCount = 5;
public Enum Type
{
Bar1,
Bar2,
Bar3,
Bar4,
Bar5,
}
use it in your attribute:
[Range(0, Item.TypeCount)]
public void BlahBlahBlah() {}
and check it at the start of your app:
public static Main()
{
if(Enum.GetNames(typeof(Item.Type)).Length != Item.TypeCount)
throw new ApplicationException ("TypeCount and number of Types do not match.\nPlease update TypeCount constant.")
}
I think in simple terms:
Enums is one "type definition", .NET use Reflection when "type descriptor navigation" is needed.
So Enums is a Type and # runtime, if you want to count the defined enums voice you need to user a reflection.
I don't see any runtime knowledge needed to get the count of enums,
because as far as I know, the count of enums cannot be changed during
runtime.
Here is the mistake in your reasoning: Yes, the count of enums cannot be changed during runtime. However, it can be changed between runtime:
A.dll - version 1
public enum Foo { A }
A.dll - version 2
public enum Foo { Bar, Baz }
Replace version 1 of A.dll with version 2. The count of enums has changed (and the names of the values as well).
Why does C# have to use reflection to get the count of enums? Why
can't it do so during compile time?
It could do so. But then you would run into the problem above. The compile-time calculated value could become incorrect.
In the "C# Coding Standard" by Juval Lowy available from www.idesign.net, the recomendation is made to use the C# predefined types instead of the aliases in the System namespace, e.g.:
object NOT Object
string NOT String
int NOT Int32
What is the benefit of this? How do they differ? I have followed this advise in my own coding but never knew how they differed.
The main time they are unexpectedly different is when someone is stupid enough to call a type (or property /field/etc) String (for example), since string always refers to global::System.String, where-as String could be YourNamespace.String.
The closest you can get to the C# alias is #string, which tends to stick out like a sore thumb.
I prefer the C# aliases.
btw, here's a fun way to mess with anyone using dynamic too much:
using dynamic = System.Object;
They don't really differ. Personally I use the aliases too, but Jeff Richter advocates the exact opposite. The generated code will be exactly the same. Use whichever you find most readable (and try to be consistent).
One thing most people agree on: when writing an API, use the type name rather than the alias, so:
int ReadInt32()
rather than
int ReadInt()
the int part doesn't matter here - it's not part of the name, and can be displayed appropriately to any consumer using any language... but the method name should be language-neutral, which means using the type name.
One place where you have to use the alias is when specifying the underlying type for an enum:
enum Foo : byte // Valid
enum Foo : System.Byte // Invalid
In addition to what Jon said here is another difference.
var x = (Int32)-y; // Does not compile.
var x = (int)-y; // Negates the value of y and casts as an int.
This is because of a grammar disambiguation rule defined in ยง7.6.6 of the C# Programming Language specification.
I think using the 'blue' int, string, etc.. might be a little more intuitive to read. Otherwise, I use the class when calling a static method on it i.e. Int32.TryParse()
I always use the aliases when specifying the type in a parameter, property or method signature or field (so: almost everywhere) except when calling a static member on such a type.
String.Format("{0}", 1);
Int32.Parse("123");
String.IsNullOrEmpty(value);
Here's another compiler-based difference:
public enum MyEnum : Byte {Value1, Value2} //does not compile
public enum MyEnum : byte {Value1, Value2} //ok
The only difference is that they're nicer to read (this of course is a matter of opinion). The compiled result is exactly the same bytecode.
The Entity Framework code generator uses predefined types, so if you want to be able to implement the Visual Studio 2017 coding style rules fully you will need to choose predefined types (int instead of Int32, etc). Otherwise your generated code will not be in compliance.
(Options->Text Editor->C#->Code Style->General->predefined type preference)