-
Notifications
You must be signed in to change notification settings - Fork 4.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Proposal: PrimitiveValueType and Generic Pointers #2209
Comments
This seems somewhat similar (if not a duplicate) to the unmanaged generic type constraints. #126 |
This seems really good for interop purposes. Since primitive types can only contain other primitive types, fixed buffers or pointers: We can use sizeof operator on primitive types, such that size may be known in compile time. For this purpose there should be a way to tell the compiler about packing etc. If that becomes possible, generic context we will be able to say fixed (TPrimitive* ptr = &Foo[0])
ptr->X = 5; |
@zahirtezcan Currently you can use |
@HaloFour Attributes are for the run-time to determine the size and layout of the structure though. But if compiler can detect size and layout statically; we can use sizeof on primitive structures and that will be whole new level for pointer/interop/memory operations |
@zahirtezcan Actually the |
Could it be used for implementing units of measure? #144 |
+1 Lack of generic pointers is one of my biggest pain points with C#. |
@MikePopoloski - about generic pointers. I am curious about particular scenarios. |
@VSadov: I was migrating the proposal I had submitted to codeplex. Now, for what I can read through #126 and #118, my proposal is not a duplicate since I meant the last two features proposed in my first post here -that is generic pointers and fixed-type buferring- for unsafe contexts. @zahirtezcan: exactly! @dsaf: I don't see why not. It would nice to have user-defined literals as in C++11, so you can do something like: public primitive Radian
{
…
public static Radian operator _rad;
public static implicit operator Radian(int value)
{
return new Radian((value % 360) * Math.PI / 180f);
}
public static implicit operator Radian(float f)
{
// do the corresponding calculation here ...
}
...
} So when you use it like @MikePopoloski: thanks! |
@VSadov More of the former than the latter. Things like reading binary files from disk, writing binary blobs to the network, or manipulating native memory blocks allocated for maximum control of cache layout (for example, particle systems). I usually end up using an IL-rewriting process to let me read and write generic pointers from/into a native memory block, since the CLR supports it just fine. If that, and the calli instruction were exposed to C# code it'd make me super happy. I'd no longer need to run the cumbersome IL rewriting build step. |
@MikePopoloski: "Things like ..." +1 on that |
Would it lift the unpleasant constants limitation? https://msdn.microsoft.com/en-us/library/e6w8fe1b.aspx
I want to be able to pass e.g. a DateTime or a TimeSpan or a Vector2 to a custom attribute, but there is no way to do this at the moment. Should it be a separate issue or the current one covers it? |
Interesting question, @dsaf . To be honest, I believe it goes beyond the scope of my suggestion since it would most likely requiere a deeper change in the compiler than adding a "primitive" type. The thing is that only "simple" built-in types (plus strings) can be declared as constants, leaving out, for this case, user-defined primitives which are initialized at runtime. In order to remove such restriction the compiler should be capable of detecting beforehand which primitives can be deemed as "simple" types, and therefore, that can be assigned at compile time. And that is a requirement that imvho should be part of a separate issue. |
I was thinking that this:
Would lead to this:
It's interesting that custom attribute constructors accepting non-primitive parameters are allowed to be declared but not to be used :) |
At first, for a moment, I thought the same as you have, but then I realized that there would be more in a type to be considered simple by the compiler than be redefined as a primitive, or otherwise, structs like DateTime, TimeSpan and Vector2 would already be allowed to be declared as constants in the current version of .NET. |
And of course, if I'm wrong, then that would be a welcome feature to have as a result of the proposed primitive type (that is, without the need of submitting a separate issue). |
I believe that such changes would require modifications to the CLR, particularly where those constants are to be used with attributes. The limitations on what kinds of values can be encoded and deserialized for attributes are set by the runtime and are a relatively short list of very easy to serialize values, namely integral types, For the most part it seems that this |
Indeed, but having a primitive type in the language would ease such task if used as a required constraint (that is, not allowing type declared as structs for generic pointers even if they hold no reference types within). So, the only way to have generic pointers would be by the use of primitives. |
This branch could really help to bring PrimitiveValueType base class to life: http://xoofx.com/blog/2015/09/27/struct-inheritance-in-csharp-with-roslyn-and-coreclr/ |
@Ultrahead I don't see how that branch does anything to make this proposal possible. You still have the problem that dereferencing that pointer requires that the compiler know at compile time the exact offset in bytes of every member or element. The compiler can't know that with generic methods. As for the branch itself, calling that "struct inheritance" seems like a bit of a stretch. A form of struct composition maybe. The behavior would probably not be what people would expect, especially the slicing for upcasting which makes downcasting impossible. |
@Ultrahead @HaloFour Actually, I like the idea of struct inheritance. The problem we run into is the meaning of interface implementations. You should be able to override the implementation of a method provided by the base struct, but that is incompatible with the tearing you get when you cast to the base struct. |
@HaloFour: At compile time, the compiler will know the size of each type of primitive. So, couldn't that task be endorsed to the CLR so that it infers it at runtime, instead? |
We definitely need a way to express/enforce blittable structs (so that if someone add a managed field, we can detect it) and enforce this at generic constraint level, to be able in the end for example, to take a pointer from it (and pass this pointer to a native method then). As @MikePopoloski mentioned, we are currently workaround it by IL rewriting this, just get an access to this feature which is very annoying (In SharpDX for example, it is all around used, declared in this file, and IL rewrite here, and used for example here) In the language, it could also be just a System attribute (Blittable), and on the constraint, we could specify constraints on attributes ( |
Also note that similar things can be done using typed references: link Of course, this abuses the internal structure of a typed reference, but it does exactly what I want in a very efficient manner. |
neat! didn't know that _makeref was also working with generics |
I guess my proposal here is a redundant form of this one Unmanaged generic type constraint + generic pointers Note that this proposal however does not require a new type specifier. |
Enthusiastically +1'ing this proposal, having generic pointers would be a very welcome addition to C# for me. A couple of things I'd do differently, though:
|
Issue moved to dotnet/csharplang #492 via ZenHub |
The idea here is to create a new type, say, "PrimitiveValueType" that would inherit directly from ValueType, and would not allow declaring reference-type field members, only value-type fields’ members that do not hold reference-types. For example:
This would also open the door another proposed feature: Generic Pointers. Take for instance the following operation:
By redefining types like int, single, double, bool, and so on so forth, so that they become specifications of PrimitiveValueType, fixed-type buferring could be enhanced so that any type defined as primitive is supported. Example:
For reference, this proposal is related to this discussion on codeplex: http://roslyn.codeplex.com/discussions/543883
The text was updated successfully, but these errors were encountered: