Run this code and check what's the best for you:

 CHK ;
set string="a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z"
set lfs=$listfromstring(string)
set tags="x,d,blabla,m",tagl=$listfromstring(tags)
set stringd=","_string_","
kill arrstr for i=1:1:$length(string,",") set arrstr($piece(string,",",i))=i
kill arrtag for i=1:1:$length(tags,",") set arrtag($piece(tags,",",i))=i
;
//$order the worst
set hh=$zhorolog for i=1:1:1000000 for j=1:1:$listlength(tagl) set tag=$list(tagl,j) set hhh=$zhorolog
write !,"$ll&$li: ",$justify($fnumber(hhh-hh,"",6),10)
set hh=$zhorolog for i=1:1:1000000 for j=1:1:$length(tags,",") set tag=$piece(tags,",",j) set hhh=$zhorolog
write !,"$l&$p: ",$justify($fnumber(hhh-hh,"",6),10)
set hh=$zhorolog for i=1:1:1000000 set tag="" for  set tag=$order(arrtag(tag)) quit:tag=""  set hhh=$zhorolog
write !,"$o: ",$justify($fnumber(hhh-hh,"",6),10)
//
write !!!!
set hh=$zhorolog for j=1:1:$length(tags,",") set tag=$piece(tags,",",j) for i=1:1:1000000 if $data(arrstr(tag)) set hhh=$zhorolog
write !,"$d: ",$justify($fnumber(hhh-hh,"",6),10)
set hh=$zhorolog for j=1:1:$length(tags,",") set tag=$piece(tags,",",j),tagd=","_tag_"," for i=1:1:1000000 if stringd[(tagd) set hhh=$zhorolog
write !,"[: ",$justify($fnumber(hhh-hh,"",6),10)
set hh=$zhorolog for j=1:1:$length(tags,",") set tag=$piece(tags,",",j),tagd=","_tag_"," for i=1:1:1000000 if $find(stringd,tagd) set hhh=$zhorolog
write !,"$f: ",$justify($fnumber(hhh-hh,"",6),10)
set hh=$zhorolog for j=1:1:$length(tags,",") set tag=$piece(tags,",",j) for i=1:1:1000000 if $listfind(lfs,tag) set hhh=$zhorolog
write !,"$lf: ",$justify($fnumber(hhh-hh,"",6),10)
set hh=$zhorolog for j=1:1:$length(tags,",") set tag=$piece(tags,",",j),tagd=","_tag_"," for i=1:1:1000000 if $match(stringd,".*"_tagd_"{1}.*") set hhh=$zhorolog
write !,"$match: ",$justify($fnumber(hhh-hh,"",6),10)
quit

Nice one, just notice that your util can copy properties between different types of objects.

Did you checked it with multi dim properties, relationships, arrays, lists, serials,  streams, calculated, etc.?

Notice that if obj1 and obj2 are of the same class then use %ConstructClone. It is part of the %Library.RegisteredObject class

http://docs.intersystems.com/latest/csp/docbook/%25CSP.Documatic.cls?PAGE=CLASS&LIBRARY=%25sys&CLASSNAME=%25Library.RegisteredObject#METHOD_%ConstructClone

$GET(pDni)?8N in the GetLetter method where your input is 8 digits and the output is the corresponding letter.

In ValidateDni your input is 8 digits and one uppercase letter so there you should use $GET(pDni)?8N1U

So now the code will be something like this:

ClassMethod GetLetter(pDni As %String) As %String
{
    set correspondence = $LISTBUILD("T","R","W","A","G","M","Y","F","P","D","X","B","N","J","Z","S","Q","V","H","L","C","K","E")
    
    set letter = ""
    
    if ($get(pDni)?8N){
        set number = (pDni # 23)+1
        set letter = $LISTGET(correspondence,number)
    }
    
    quit letter
}
/// <br><b>0</b> Dni OK
/// <br><b>-1</b> Dni error

ClassMethod ValidateDni(pDni As %String) As %Integer
{

    set response = -1
    
    if ($get(pDni)?8N1U){
        //Get the numbers of Dni
        set auxNumber = $EXTRACT(pDni,1,8)
        
        //Get the letter of Dni
        set auxLetter = $EXTRACT(pDni,9,9)
        
        //Calculate the letter of the dni
        set calculatedLetter = ..GetLetter(auxNumber)
        
        if (auxLetter = calculatedLetter){
            set response = 0
        }        
    }
    
    quit response
}

I think that in GetLetter the condition should be if $get(pDni)?8n to validate that pDni contain 8 exactly 8 digits

And in ValidateDni the condition should be if $get(pDni)?8n1u to validate that pDni contains exactly 8 digits followd by an uppercase letter.

Also in ValidateDni instead of ##class(DKI.Common.Utils.Utilitades).GetLetter(auxNumber) you should do ..GetLetter(auxNumber) in this way when you put both methods in the same class the class name doesn't have to be DKI.Common.Utils.Utilitades

More about pattern matching can be found here:

https://docs.intersystems.com/latest/csp/docbook/DocBook.UI.Page.cls?KEY...

And about arithmetic&logic precedence:

http://docs.intersystems.com/irislatest/csp/docbook/DocBook.UI.Page.cls?...