question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

[Feature] Would it be possible to declare fields?

See original GitHub issue

Hey, just discovered this package, looks amazing! Thank you for your time building this! 😄

I have a question/proposal, would it be possible to support declaring fields? This would be useful when the type of such fields is not accessible from C# (eg. with internal types from other assemblies). Accessing and using those fields from IL would be easy, but from the readme it doesn’t look like it’s currently possible to declare the first right now? 🤔

Rationale

In the Microsoft.Toolkit.HighPerformance package (source here, API browser here) we have a number of types that basically act equivalent for the System.ByReference<T> type from CoreCLR, which is unfortunately internal (made a proposal about making it public a while back (here), but that’s not really planned). The workaround I came up with is to just use a Span<T> as proxy for the ByReference<T> type, using MemoryMarshal.CreateSpan<T>(ref T, int). This is kinda ok when we can reuse the Span<T>.Length property for other purposes (basically as if it was just another int field in the parent type), but it’s just unnecessary overhead when that’s not needed. Specifically, in the Ref<T> and ReadOnlyRef<T> types.

I was toying with the idea of just writing a part of that type directly in IL, declaring a ByReference<T> field and simply using that directly from the various available APIs. Of course, this would only be for .NET Core 2.1, .NET Core 3.1 and .NET 5, and not for the other targets. Would something like this be possible? I’m actually curious in general even outside of this specific case 😄

Something like (just the idea):

[LocalField("System.ByReference`1", "reference")]
public readonly ref struct Ref<T>
{
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public Ref(ref T value)
    {
        Type
            byRefType = Type.GetType("System.ByReference`1").MakeGenericType(typeof(T)),
            parameterType = typeof(T).MakeByRefType();
        MethodRef cctor = MethodRef.Constructor(byRefType, parameterType);

        Ldarg_0();
        Ldarg_1();
        Newobj(cctor);
        Stfld(FieldRef.Field(byRefType, "reference"));
    }

    public ref T Value
    {
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        get
        {
            Type byRefType = Type.GetType("System.ByReference`1").MakeGenericType(typeof(T));

            Ldarg_0();
            Ldflda(FieldRef.Field(byRefType, "reference"));
            Call(MethodRef.PropertyGet(byRefType, "Value"));

            return ref IL.ReturnRef<T>();
        }
    }
}

Again congrats again for building this, I’ve been looking for something like this for a while! 🚀

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Comments:23 (11 by maintainers)

github_iconTop GitHub Comments

3reactions
Sergio0694commented, Jun 27, 2020

Yeah getting Fody involved would make the whole thing even harder to maintain, you’re right. After all, this is basically just a temporary workaround, ideally I’d just want to switch to proper ref T fields if/when they will become available (maybe C# 10 and .NET 6? Who knows!). This is an incredibly powerful workaround for the moment though! 😄 And it’s already miles better than just hacking around with a fake Span<T> with unused length.

About that .deps.json file, not sure, but I guess someone reviewing that PR will be able to chime in on that. Yeah I’d agree with you, this solution is effectively much easier to implement than actually writing new support for declaring fields with InlineIL. That said, I’ll still definitely be using your lib in the future in other projects, as it’s just great! 🚀

3reactions
ltrzesniewskicommented, Jun 27, 2020

You’re welcome! 😄

This could also have been implemented in a slightly different way, for example by using a Fody in-solution weaver that would inject the necessary code and assembly reference, but it would probably be harder to read and maintain than the way I made it.

One more thing I thought of after posting this: System.Private.CoreLib will be referenced in the .deps.json file. I don’t know if it’s an issue, hopefully not.

I guess I won’t be adding the feature you asked for InlineIL in the end, since the way I’ve shown here solves the problem much better anyways.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Defining feature class properties—ArcMap | Documentation
All feature classes have a set of required fields necessary to record the state of any particular object in the feature class. These...
Read more >
Define fields in tables—ArcGIS Pro | Documentation
Field names are the names you give to the columns in a table. The names should indicate what data is contained in each...
Read more >
Fields - C# Programming Guide
A field in C# is a variable of any type that is declared directly in a class or struct. Fields are members of...
Read more >
Add Specific Fields from feature class to feature
I am trying to create tools with specific two fields adding new information into from existing SDE feature class to SDE existing feature...
Read more >
Public class fields - JavaScript - MDN Web Docs - Mozilla
Public instance fields exist on every created instance of a class. By declaring a public field, you can ensure the field is always...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found