Skip to content
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: stack-only struct #231

Closed
ygc369 opened this issue Mar 7, 2017 · 12 comments
Closed

Proposal: stack-only struct #231

ygc369 opened this issue Mar 7, 2017 · 12 comments

Comments

@ygc369
Copy link

ygc369 commented Mar 7, 2017

C# should provide stack-only struct, which can only be stored in stack, and can't be embedded in any class (but can be embedded in another stack-only struct).
This kind of stack-only struct can have destructor method, which would be executed when the struct goes out of scope.
For example:

stackonly struct A
{
    int a;
    .......
    ~A()   //destructor 
    {
        ........
    }
}
static void foo()
{
    A test=new A(); //alloc memory from stack
   ......
} //destructor of "test" would be executed here automatically

class B
{
    A field; //compile error! A is stack-only!
}
@svick
Copy link
Contributor

svick commented Mar 7, 2017

What's the use case for this? Isn't it in effect just a less explicit and more limited (e.g. likely not usable in async methods) version of using?

Also, how do you ensure the structure is really stack-only and cannot be for example instantiated using Activator.CreateInstance()?

@HaloFour
Copy link
Contributor

HaloFour commented Mar 7, 2017

What are some use cases for this? How would it work with ref locals/returns? How would it work with pointers in general? How would it work with generic methods?

@ufcpp
Copy link

ufcpp commented Mar 7, 2017

dotnet/roslyn#161

@ygc369
Copy link
Author

ygc369 commented Mar 7, 2017

@svick
@HaloFour
It seems that Span is stack-only, this is just an example for the use case.
I want to create user-defined stack-only struct for another use case. Just like svick said, it's another version of using, but it can force user to release resources.
If I write a function library for others, although I provide dispose function, users can still ignore it and forget to release resources. I can't force them to use "using". So if C# support stack-only struct, I can use it to wrap my functions to ensure releasing resources.
For example:

stackonly struct A
{
    FileStream file;
    public A(string filename)
    {
        file = new FileStream(filename, FileMode.Open);
    }
    ......  //other operation functions
    ~A()
    {
        if(file)
        {
           file.Close();
           file=null;
        }
    }
}

@yaakov-h
Copy link
Member

yaakov-h commented Mar 7, 2017

What if I need to keep your A alive across an await or yield or similar?

Forcing something to only be able to stay on the stack limits it's use considerably.

@ygc369
Copy link
Author

ygc369 commented Mar 7, 2017

@yaakov-h
What if I change the limitation from stack only to local variable only? That would allow await and yield.

@yaakov-h
Copy link
Member

yaakov-h commented Mar 7, 2017

I don't think that would, because the compiler-generated state machine is a class.

@ygc369
Copy link
Author

ygc369 commented Mar 8, 2017

@yaakov-h
I think that would, if the compiler treat them as special cases. When the compiler see this struct only used as local variables and not embedded in any classes, it should allow. No runtime checking is needed.

@Thaina
Copy link

Thaina commented Mar 8, 2017

remind me of stackalloc keyword

@omariom
Copy link

omariom commented Mar 8, 2017

It will allow to encapsulate refs and Spans
https://github.com/dotnet/coreclr/issues/5860

@ufcpp
Copy link

ufcpp commented Apr 25, 2017

struct A
{
    int value;

    // Error CS8170
    ref int Value => ref value;

    // OK, but should this be error if Span<T> becomes stack-only?
    unsafe Span<byte> AsBytes() => new Span<byte>(Unsafe.AsPointer(ref value), 4);
}

stackonly struct B
{
    int value;

    // Could this be OK?
    ref int Value => ref value;

    // OK?
    unsafe Span<byte> AsBytes() => new Span<byte>(Unsafe.AsPointer(ref value), 4);
}

@ygc369
Copy link
Author

ygc369 commented Nov 16, 2017

ref struct in C# 7.2 has implemented stack-only struct, but seems not to support finalizer. I will close this and open another issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

8 participants