0

In my case , I have bunch of values of same type , let's say floats :

        float value1 = 1.2f;
        float value2 = 1.5f;
        float value3 = 2.3f;

Now I need a pointer or a reference value can get a instance of this floats and do operations on it.

in C++ :

    float* float_reference;

Now I want to set float_reference to value1 So in my functions every computation put result in value1.

Notes : - I don't want to use classes - I don't want to use ref keyword in a functions - I don't want to use unsafe keyword

I just need to do it as I said like C++ , Is there any other way around ?

EDIT 1 : This is why I can't use unsafe , Here's Example :

using System.Windows;


namespace ValueUpdater
{

    public unsafe partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            //// need to assign one of floats to reference object
        }

        float value1 = 1.2f;
        float value2 = 1.5f;
        float value3 = 2.3f;

        float* value_ref; ////// Can't Make this pointer!

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            /// Need to change the reference here
            fixed (float* value_ref = &value3) {
                *value_ref += 2;
            };
        }

        private void Button_Click_1(object sender, RoutedEventArgs e)
        {
            /// Need to change the reference here
            /// But can't use value_ref = &value3 without re-initalize
             fixed (float* value_ref = &value3)
            {
                *value_ref -= 2;
            };

        }

        private void Button_Click_2(object sender, RoutedEventArgs e)
        {
            Output.Content = value3.ToString();
        }
    }
}

XAML :

<Window x:Class="ValueUpdater.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:ValueUpdater"
        mc:Ignorable="d"
        Title="MainWindow" Height="354.017" Width="368.698">
    <Grid>
        <Button Content="Add 2" Margin="0,28,27,0" VerticalAlignment="Top" HorizontalAlignment="Right" Width="75" Click="Button_Click"/>
        <Button Content="Sub 2" Margin="0,55,27,0" VerticalAlignment="Top" HorizontalAlignment="Right" Width="75" Click="Button_Click_1"/>
        <Button Content="Reset" Margin="0,83,27,0" VerticalAlignment="Top" HorizontalAlignment="Right" Width="75"/>
        <Button Content="Print" Margin="0,0,27,20" HorizontalAlignment="Right" Width="75" Height="20" VerticalAlignment="Bottom" Click="Button_Click_2"/>
        <Label x:Name="Output" Content="Output" HorizontalAlignment="Left" Margin="19,22,0,0" VerticalAlignment="Top" Width="182"/>

    </Grid>
</Window>
12
  • Try following : uint output = BitConverter.ToUInt32(BitConverter.GetBytes(value1),0); Commented Feb 26, 2020 at 11:49
  • 1
    @jdweng that does something completely different... Commented Feb 26, 2020 at 11:52
  • Can you explain why you do not want to use the C# language as it usually works? Are you passing these values to a C++ function? Commented Feb 26, 2020 at 11:53
  • 1
    "I just need to do it as I said like C++ " - ref float is the equivalent in C#; ref float float_reference = ref value1; (safe C#) is virtually identical to float* float_ptr = &value1; (unsafe C#) - the only difference is that the GC understands the first version, so it doesn't need pinning etc; I'd really love to understand why you don't want to use ref, when it is the equivalent code (note: ref is usually used with parameters etc, but: ref-locals are a thing) Commented Feb 26, 2020 at 11:56
  • @Marc Gravell : I know exactly what it does and what the OP wants to do. Commented Feb 26, 2020 at 11:58

2 Answers 2

2

I don't want to use classes - I don't want to use ref keyword in a functions - I don't want to use unsafe keyword

Nope; those are the three options for conveying state in a reference-like way:

  1. unmanaged pointers (unsafe)
  2. managed pointers (ref)
  3. indirectly as fields on a reference-type (class)

You could also use indirection via an float[] array, Span<float>, or Memory<float>, but then you also need to convey the index; frankly, those are all just indirect ways of getting a managed pointer to a value, so they're really just special cases of "2".

Sign up to request clarification or add additional context in comments.

4 Comments

so Can I be SURE only these options are possible ?
IMHO if OP doesn't want to use ref and class the only thing left is unmanaged pointers. GC pins might work as well but actually using these might be painfull.
@Mateusz I don't mean this disparagingly, but: most times I see people use unmanaged pointers in C#, they're a: incorrectly implemented, and b: unnecessary; I'd really rather understand the intended use-case before pushing people in that direction; usually, you should prefer them in the order from the bottom of the list upwards, i.e. "fields on a class" first, "ref" second (and I'm including arrays/spans/etc in here), "unmanaged pointers" only as a last resort
@MarcGravell I completely agree with you on that one. I was just thinking about using GC pins instead of unmanaged pointers.
0

The key usage in the question is this:

        float value1 = 1.2f;
        float value2 = 1.5f;
        float value3 = 2.3f;

        float* value_ref; ////// Can't Make this pointer!

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            fixed (float* value_ref = &value3) {
                *value_ref += 2;
            };
        }

        private void Button_Click_1(object sender, RoutedEventArgs e)
        {
            fixed (float* value_ref = &value3)
            {
                *value_ref -= 2;
            };

        }

In that code, you are always updating value3. If we assume that this code is illustrative and that you intended to update indirectly via value_ref; we can't keep a ref float as a field (even inside a ref struct), so fundamentally, I think the best way to reconsider this is via an array, i.e.

float[] values = new [] {1.2f, 1.5f, 2.3f};
int value_index;

Now we can use:

values[value_index] += 2;
...
values[value_index] -= 2;

Not quite the same as the C++, but: very effective and simple.

4 Comments

Sorry marc but the code was why I can't use unsafe not my real code , I have a singleton class , Using an array is a good idea , I liked it but Still I think it should be done in a more clear way . thanks , temporary I accept your method.
@J.Mcgill the thing you want doesn't exist; you can't store ref float as a field, and storing float* is possible, but requires lots of consideration re pinning, as C# has a compacting GC that can only respect managed references (ref float), not unmanaged references (float*); indirection via an array (or span) is therefore probably your best bet
Now i see why C++ is the best :)
@J.Mcgill ooh, them's fightin' words :) btw, if you allocated this as unmanaged memory, or took a GC pin against it, you could store the pointer directly; that doesn't mean that it is a good way of solving the scenario, though

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.