-1

I use IL Spy to decompiler record code, e.g:

public record Record1(string Name);

decompiler in IL Spy

using System;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using System.Text;

public class Record1 : IEquatable<Record1>
{
    protected virtual Type EqualityContract
    {
        [System.Runtime.CompilerServices.NullableContext(1)]
        [CompilerGenerated]
        get
        {
            return typeof(Record1);
        }
    }

    public string Name
    {
        get;
        init;
    }

    public Record1(string Name)
    {
        this.Name = Name;
        base..ctor();
    }

    public override string ToString()
    {
        StringBuilder stringBuilder = new StringBuilder();
        stringBuilder.Append("Record1");
        stringBuilder.Append(" { ");
        if (PrintMembers(stringBuilder))
        {
            stringBuilder.Append(" ");
        }
        stringBuilder.Append("}");
        return stringBuilder.ToString();
    }

    protected virtual bool PrintMembers(StringBuilder builder)
    {
        builder.Append("Name");
        builder.Append(" = ");
        builder.Append((object?)Name);
        return true;
    }

    [System.Runtime.CompilerServices.NullableContext(2)]
    public static bool operator !=(Record1? r1, Record1? r2)
    {
        return !(r1 == r2);
    }

    [System.Runtime.CompilerServices.NullableContext(2)]
    public static bool operator ==(Record1? r1, Record1? r2)
    {
        return (object)r1 == r2 || (r1?.Equals(r2) ?? false);
    }

    public override int GetHashCode()
    {
        return EqualityComparer<Type>.Default.GetHashCode(EqualityContract) * -1521134295 + EqualityComparer<string>.Default.GetHashCode(Name);
    }

    public override bool Equals(object? obj)
    {
        return Equals(obj as Record1);
    }

    public virtual bool Equals(Record1? other)
    {
        return (object)other != null && EqualityContract == other!.EqualityContract && EqualityComparer<string>.Default.Equals(Name, other!.Name);
    }

    public virtual Record1 <Clone>$()
    {
        return new Record1(this);
    }

    protected Record1(Record1 original)
    {
        Name = original.Name;
    }

    public void Deconstruct(out string Name)
    {
        Name = this.Name;
    }
}

I read class - 'POCO' definition and think it's true, but it's not like below kind simple property POCO.

public class Record1
{
    public string Name {get;set;}
}

Because it contains behavior like

  • immutable by {get;init;}
  • value equals by override Equals
    public virtual bool Equals(Record1? other)
    {
        return (object)other != null && EqualityContract == other!.EqualityContract && EqualityComparer<string>.Default.Equals(Name, other!.Name);
    }

But I'm not sure for it.

Wei Lin
  • 3,591
  • 2
  • 20
  • 52
  • 1
    POCO really isn't a technical term in regards to any language feature in C# . Yes its produces a class. Why do you need to know this, maybe we can answer it better? Additionally, I think any answer to this (as is) will be subjective, mainly because the very term POCO is ill defined and not part of any specification – TheGeneral Nov 23 '20 at 02:31
  • It's not POCO, it's depending on the `IEquatable` interface along with the other base framework classes. POCO shouldn't rely on these, in that class they do. Maybe someone else could chime in about this? – Trevor Nov 23 '20 at 02:43
  • @TheGeneral Some one ask me the question `Is C# 9 Record also POCO`, and I'm not sure for it. – Wei Lin Nov 23 '20 at 02:47
  • You can derive *your opinion* from the question you've [linked](https://stackoverflow.com/questions/250001/poco-definition)... My opinion - if does not really matter if one calls record POCO or not... – Alexei Levenkov Nov 23 '20 at 03:03
  • 3
    The first question i would be asking the person who asked you is, "Define POCO technically", If that means it cant include BCL interfaces, then its not POCO. If it means that it cant be a compiler generated class... This is where the term POCO breaks down. If you have class with an async method, that class now has a dependency on a framework `IAsyncStateMachine` implementation. Even classes have a dependency on the BCL object class. Its like where are we drawing the line here... The truth is we cant as there is technically no such thing in the .net or C# specs that defines POCO – TheGeneral Nov 23 '20 at 03:04
  • @The General could u answer below? it's awesome! – Wei Lin Nov 23 '20 at 03:06
  • 1
    @TheGeneral I even wasn't cognizant of what POCO is. Thanks for the comment. I have learned a new thing from you. – Soner from The Ottoman Empire Nov 23 '20 at 03:19
  • @snr [Welcome to the 10,000](https://xkcd.com/1053/) – Dai Nov 23 '20 at 03:42
  • @TheGeneral, POCO is a well known term came from POJO two decades ago when ORMs start to rise. Strong subjective opinions should be avoided. – Allan Xu Apr 14 '23 at 19:10

1 Answers1

0

The problem here is POCO is actually not a technical term, it's more a colloquial term to describe a loose set of behaviors/properties which has its origins in other languages and at best context dependent.

Furthermore, there are actually no reference to the word POCO (or in its expanded form) in the .Net or C# specifications. So all we can do is use such language loosely based on its colloquial meaning. Which is an object that has no dependencies on external frameworks.

When you compile a Record it creates a fairly pedestrian class which implements a BCL interface.

Is this enough for it to be now classed as a complex object (because it has a contract to a BCL interface)? Well I guess it depends on who you ask.

And if the answer is yes, where do we draw the line? Are classes with async methods that have dependencies on a compiler generated IAsynStateMachine implementation, or closures, or the many other instances where the compiler generates dependencies POCO?

In short, the term POCO has no real use. It only has if the people who are discussing the concept can agree on a narrow well-defined definition.

So if someone asks you if something is POCO, you should ask them back "stringently define POCO for me".

halfer
  • 19,824
  • 17
  • 99
  • 186
TheGeneral
  • 79,002
  • 9
  • 103
  • 141
  • 1
    What's with the shade on Martin Fowler? – Dai Nov 23 '20 at 03:32
  • "In short, the term POCO has no real use" - in the context of ORMs and MVVM it *definitely* has applicable usage. Granted, it still isn't _strictly defined_, but in those contexts it's generally understood to mean the ORM or MVVM framework does not rely on you using some base-class or interface (e.g. Entity Framework doesn't require your entity classes inherit from any `BaseEntity`, while WPF _does_ require you to implement `INotifyPropertyChanged` and that property setters need to have side-effects, hence WPF VMs cannot be POCOs). – Dai Nov 23 '20 at 03:33
  • @Dai hah, i didnt think that would slip past unnoticed... Nothing really, though its the same as Eric Evens. People follow these evangelists like a religion, and a lot of it should be taken with a grain of salt – TheGeneral Nov 23 '20 at 03:34
  • @Dai i also agree, if you define the usage of POCO, then its more useful, however asking if something is POCO without such stringent context is futile. Especially in this context. In short there is no language feature or definition of term POCO, and if there, its context dependent – TheGeneral Nov 23 '20 at 03:36
  • @Dai Martin Fowler shade removed ;) – TheGeneral Nov 23 '20 at 03:40
  • If it need to define POCO then what word can represent `public class Type {public string ID{get;set;}}` this code? – Wei Lin Nov 23 '20 at 03:44
  • 1
    @Wei here is the thing, even by the narrowest, that is probably POCO. Its when you start adding interfaces or fur to a class the definition gets really unusual and blurry. You could even call it a DTO, if used to transfer data. You could just call it a simple class with just properties .. "*SCWJP*" – TheGeneral Nov 23 '20 at 03:47