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

Draft using records for data types in FileFormats.W3d #809

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

charliefoxtwo
Copy link
Contributor

@charliefoxtwo charliefoxtwo commented Jan 26, 2024

I was looking at enabling nullable reference types in OpenSage.FileFormats.W3d, and found a lot of these immutable data types. I wanted to propose moving these over to records. Records are purpose-built immutable reference types with a clear contract and I think this would be a good use case for them.

I've only migrated a few types (including the core W3dChunk) in this draft as a sample, as there are a lot of types to migrate so I don't want to go all-in without first making sure it's a direction we want to go in. At a glance it definitely looks possible. As only a few types have been migrated and one of them is a base type for many things, this will not compile as-is.

One downside I could see is that large migrations like this can muddy up the commit history. Also the phrase "if it ain't broke, don't fix it" comes to mind. This is really just one way of getting to nullable reference types in this project. The other might look something like this (note the null! assignment):

public class MyClass
{
    public Foo Prop1 { get; private set; } = null!;
    
    internal static MyClass Parse(...)
    {
        var myClass = new MyClass();
        var foo = Foo.Parse(...);
        myClass.Prop1 = foo;
        return myClass;
    }
}

What I don't like about this method is that it relies on the developer to verify Prop1 is actually set, which to me defeats the purpose.

Another alternative:

public class MyClass
{
    public Foo Prop1 { get; }
    
    public MyClass(Foo prop1)
    {
        Prop1 = prop1;
    }
    
    internal static MyClass Parse(...)
    {
        var foo = Foo.Parse(...);
        return new MyClass(foo);
    }
}

But now we're just getting closer to record types and at that point, I figure we just lean into them?

@charliefoxtwo
Copy link
Contributor Author

charliefoxtwo commented Jan 26, 2024

Discussion on discord also floated the idea of using record structs, which should be almost identical in code (one extra word) but may offer performance improvements.

I still plan to wait for confirmation that we're ok with this migration before I move forward with it.

@charliefoxtwo
Copy link
Contributor Author

Upon further investigation, using record structs likely will not be an option as structs are not inheritable in C#

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

Successfully merging this pull request may close these issues.

None yet

1 participant