Differenze da Py a C#

import Rhino as rh


def GetCrvs():

    go = rh.Input.Custom.GetObject()
    
    go.SetCommandPrompt("Select Object")
    
    go.Get()

    if go.CommandResult() != rh.Commands.Result.Success: return go.CommandResult()
    
    return go


unknown = GetCrvs()

print( unknown )
print( unknown.Object(0) )
print( unknown.Object(0).Curve() )
print( unknown.Object(0).Object() )
using System;
using rh = Rhino;

object GetCrvs()
{
    rh.Input.Custom.GetObject go = new rh.Input.Custom.GetObject();

    go.SetCommandPrompt("Select Object");

    go.Get();
    
    if (go.CommandResult() != rh.Commands.Result.Success) return go.CommandResult();
    
    return go;
}

var unknown = GetCrvs();

//rh.RhinoApp.WriteLine( unknown );
//rh.RhinoApp.WriteLine( unknown.Object(0) );
//rh.RhinoApp.WriteLine( unknown.Object(0).Curve() );
//rh.RhinoApp.WriteLine( unknown.Object(0).Object() );

errore del primo WriteLine evidenziandomi unknown:

Argument 1: cannot convert from ā€˜objectā€™ to ā€˜stringā€™

errore in tutti gli altri 3 WriteLine evidenziandomi Object(0):

ā€˜objectā€™ does not contain a definition for ā€˜Objectā€™ and no accessible extension method ā€˜Objectā€™ accepting a first argument of type ā€˜objectā€™ could be found (are you missing a using directive or an assembly reference?)

cercando di convertire questo script da Py a C# sono incappato in questa situazione,
anche capendo il problema non riesco a trovare la soluzione
dal messaggio di errore unknown ĆØ un oggetto fin qui ĆØ chiaro
giustamente mi dice che non puĆ² convertire un oggetto in stringa
(anche forzando la conversione ma per ora nulla)

ora sappiamo che Py non tiene conto di nulla, qualsiasi cosa gli dai lui esegue oggetti stringe ecc
ma come in Py ĆØ possibile stampare output di quei oggetti, si dovrebbe poter fare la stessa cosa in C#?
(ovviamente usando la procedura corretta intendo)

e vabbĆØ ma non si fa cosƬ. . .

soluzione per il primo errore:

//rh.RhinoApp.WriteLine( unknown );

Console.WriteLine(unknown);

oppure in questo modo sembri che funzioni ugualmente:

rh.RhinoApp.WriteLine( $"{unknown}" );
rh.RhinoApp.WriteLine( "{0}", unknown );
rh.RhinoApp.WriteLine( Convert.ToString(unknown) );

per gli altri 3 errori rimane lo stesso messaggio

ā€˜objectā€™ does not contain a definition for ā€˜Objectā€™ and no accessible extension method ā€˜Objectā€™ accepting a first argument of type ā€˜objectā€™ could be found (are you missing a using directive or an assembly reference?)

mi sĆ  che devā€™essere indicato diversamente Object(0)

Il C# rispetta i tipi che tu dichiari.
Se dichiari che la funzione GetCrvs restituisce un object, lui il valore restituito lo considera un object.
( Questo eā€™ possibile dato che ogni oggetto discende da object )
Per cui quando tu in fase di stampa gli dici di eseguire il metodo Object, lui non trova nessun metodo Object appartenente allā€™oggetto di tipo object e ti daā€™ errore.

si su questo ci sono arrivato, ma comunque non ne vengo a capo

using sy = System;
using rh = Rhino;

rh.Input.Custom.GetObject GetCrvs()
{
    rh.Input.Custom.GetObject go = new rh.Input.Custom.GetObject();

    go.SetCommandPrompt("Select Object");

    go.Get();
    
    if (go.CommandResult() != rh.Commands.Result.Success) return go.CommandResult();
    
    sy.Console.WriteLine( go.ObjectCount );

    return go;
}

rh.Input.Custom.GetObject obj = GetCrvs();

inizialmente avevo anche provato in questo modo che mi sembrava corretto,
ma poi di dava problemi col return interno return go.CommandResult()

Cannot implicitly convert type ā€˜Rhino.Commands.Resultā€™ to ā€˜Rhino.Input.Custom.GetObjectā€™

ed avevo corretto come postato prima, ma poi proseguendo nel codice mi dava problemi col WriteLine

poi a questo punto non comprendo perchƩ se il tipo della classe sia object vada bene per entrambi
i return, mentre la classe tipizzata come questo post per nel return intermedio mi torna errore?

Daā€™ problemi percheā€™ il tipo eā€™ diverso da quello dichiarato.
Se tu dichiari che una funzione restituisce una string e poi resituisci un double, lui segnala lā€™errore.
Qui eā€™ la stessa cosa.

Lā€™ho detto sopra

Ripassa lā€™ereditarietaā€™ in C#. :wink:
Tutte le classi discendono da object, quindi ogni oggetto puoā€™ essere considerato di tipo object.

Se permetti un commento. :slight_smile:
Secondo me, utilizzare in C# metodi che possono restituire valori di tipi completamente diversi, come in questo caso, non eā€™ il modo piuā€™ semplice di procedere.
Quello che eā€™ comodo in Python puoā€™ essere scomodo in C#.

eeee che bella scoperta, in tutti gli esempi di C# che mi ero salvato, i return sono tutti con Result

unica eccezione ĆØ questa:

  private static Rhino.Geometry.NurbsCurve GetSpirial1()
  {
    var railStart = new Rhino.Geometry.Point3d(0, 0, 0);
    var railEnd = new Rhino.Geometry.Point3d(0, 0, 10);
    var railCurve = new Rhino.Geometry.LineCurve(railStart, railEnd);
   
    double t0 = railCurve.Domain.Min;
    double t1 = railCurve.Domain.Max;
   
    var radiusPoint = new Rhino.Geometry.Point3d(1, 0, 0);
   
    return Rhino.Geometry.NurbsCurve.CreateSpiral(railCurve, t0, t1, radiusPoint, 1, 10, 1.0, 1.0, 12);
  }

adesso vedo se ereditarietĆ  come da te indicata va bene :+1:

e pure, quei pochi script fatti con RCommon in Py funzionano, lo stesso codice in C# non va bene
e bisogna ri-raggionarci sopra e oltre a convertirli anche apportare le opportune modifiche :triumph: :triumph:


ps comunque mi fa strana questa motodologia:

rh.Input.Custom.GetObject GetCrvs()
{
    rh.Input.Custom.GetObject go = new rh.Input.Custom.GetObject();

se io indico una classe tipizzata come vedere sopra, e la nuova istanza oggetto sempre come indicata,
nei return sia quelli intermedi che finali, mi aspetto che venga gestita sia lā€™oggetto ma anche il risultato.

(mio pensiero ovviamente)

Restituire Result va benissimo, ma il metodo deve restituire solo oggetti di tipo Result.
E lo deve dichiarare allā€™inizio.
Non eā€™ che un tipo sia meglio di un altro ā€¦
Eā€™ solo che un metodo deve restituire sempre lo stesso tipo (quello che dichiari allā€™inizio).

Se non mischi i vari tipi tra loro non devi preoccuparti dellā€™ereditarietaā€™, almeno quando scrivi il metodo.

Non so percheā€™ quegli esempi resituiscano tipi diversi dalla stessa funzione ā€¦ a me sembra un poā€™ una stranezza :smile:.
Comunque tu controlla a cosa serve restituire tipi diversi.
Potrebbe esserci un modo semplice per fare la stessa cosa senza mischiare i tipi. :slight_smile:

Non capisco bene cosa intendi, soprattutto cosa intendi con gestita.
Ma, partendo dalle istruzioni che riporti, se tu restituisci lā€™oggetto go va benissimo.
Peroā€™ non puoi restituire oggetti di un tipo diverso.

il go nel return finale si

ma questa riga, nel return intermedio non va bene
if (go.CommandResult() != rh.Commands.Result.Success) return go.CommandResult();

anche se go.CommandResult() fa parte di rh.Input.Custom.GetObject GetCrvs()

questo mi :exploding_head: :exploding_head:

eeee magari, a saperlo. se cā€™Ć© di sicuro lo scoprirĆ². la domanda ĆØ, chissĆ  tra quanto tempo.


come far gestire ad un Metodo il return, sia con il result che con un oggetto Input.Custom.GetObject ?

Scusa, in che senso ā€œfa parteā€ ?

Per andare sul pratico ā€¦ a cosa ti serve ottenere tipi diversi da quel metodo ?
Cosa ci fai ?
(Personalmente non capisco a cosa serva una cosa simile ā€¦ :thinking:)

Poi se vuoi ricavare piuā€™ di un valore da un metodo, il modo cā€™eā€™.
Mai sentito parlare di parametri out ? :wink:

si ma usato con questo metodo: Rhino.Input.RhinoGet.GetOneObject mai usato con il Custom
(dici che sia possibile?)

se vedi il codice Py nel primo post, se il risultato nonā€™Ć© Success ritorna il risultato altrimenti ritorna go

non ci vedo una cosa strana, anzi un discorso abbastanza senzato

se il Metodo richiede un oggetto rh.Input.Custom.GetObject
e go equivale a new rh.Input.Custom.GetObject();
dopo aver esegito go.Get();
posso richiamare sia go.Object(0) che go.CommandResult()

come detto sopra se il Metodo richiede un oggetto rh.Input.Custom.GetObject
quindi allo stesso modo perchƩ il return non accetta sia go.Object(0) che go.CommandResult()

Giusto, proprio quello ! :slight_smile:

Non eā€™ questione di RhinoCommon.
Quella eā€™ una feature del C#. Se scrivi tu il metodo, la usi come e quando vuoi.

Quello si vede.
Ma quello che non capisco eā€™ cosa ci fai con un valore che non sai nemmeno di che tipo eā€™.
Quando richiami quella funzione, come utilizzi il valore restituito ?

OK, allora saprai spiegarmi come utilizzi questa cosa. :slight_smile:

Il metodo non richiede nessun oggetto. Non ha parametri.
Il tipo che scrivi prima del nome del metodo eā€™ il tipo del valore restituito, credevo lo sapessi giaā€™. :wink:

Eā€™ un oggetto di quel tipo che, per caso, in quel momento ti serve per fare i tuoi calcoli ecc. dentro a quel metodo.
E che puoi restituire dal metodo, visto che il tipo combacia.

Certo, con lā€™oggetto go ci fai quello che vuoi.

Non richiede niente. :slight_smile:
Restituisce un oggetto di tipo ā€˜Rhino.Input.Custom.GetObjetā€™.

Scusa, quale modo ?

Percheā€™, come giaā€™ accennato, quel metodo deve restituire solo oggetti di tipo
Rhino.Input.Custom.GetObject
Semplicemente percheā€™ cosiā€™ eā€™ scritto prima del nome del metodo: quello eā€™ il tipo da restituire.
Non ci sono altri ragionamenti.

Ovviamente il tipo da restituire lo decidi tu, e dopo averlo deciso, lo scrivi prima del nome del metodo.
E scrivi il resto dello script di conseguenza.

Se prima del nome del metodo scrivi float, allora il metodo dovraā€™ restituire sempre e solo valori di tipo float

Questo vale per ogni tipo, non ci sono differenze.

I linguaggi cosiddetti ā€˜tipizzatiā€™ hanno questo nome proprio percheā€™ i valori utilizzati nel programma, come variabli ecc., devono avere sempre lo stesso tipo.
Eā€™ questo che permette di compilare il programma e di ottenere un programma piuā€™ veloce di (ad esempio) un programma Python.

Eā€™ questa la caratteristica di quei linguaggi.
Devi stabilire in anticipo il tipo dei vari valori, e poi ovvaimente rispettare questa decisione nel resto del programma.

Secondo me non ha molto senso cercare di utilizzare questi linguaggi come utilizzi Python. :slight_smile:
In ogni caso provare a farlo mi sembra parecchio complicato ā€¦
Direi una cosa da fare solo se eā€™ proprio necessario.

nellā€™esecuzione, invece di scegliere lā€™oggetto, annullo il comando quindi ritorna Cancel altrimenti go

si scusa mi colpa per troppa sintesi, volevo intendere, ā€œrichiedeā€ di dare un valore di ritorno di tipo. . .

esatto a questo punto, forse il modo corretto su come formulare la domanda del post sarebbe:

ā€œcome fa Python a far accettare ai vari return, oggetti diversi?ā€

se come dici ĆØ una cosa complicata, ovviamente non ne vale la pena, ma era giusto per il piacere di sapere.

Quello si capisce.
La mia domanda (provo a riformulare :smile:) era: come utilizzi il valore resituito dopo, quando richiami quella funzione ?
Cosa ci fai di un valore che non sai che tipo sia ?

Tu hai postato solo la funzione, non lā€™intero script.
Nello script, come la usi quella funzione ?
Hai un esempio ?

Python eā€™ un linguaggio di tipo dinamico, non compilato ma interpretato.
Eā€™ piuā€™ lento appunto percheā€™ lā€™interprete ogni volta deve prima capire di che tipo di valore si tratta, e poi utilizzarlo di conseguenza.
Eā€™ la sua caratteristica.

Dicevo che eā€™ complicato far fare a C# quello che fa Python.
Percheā€™ Python questa cosa di verificare prima il tipo e quindi agire di conseguenza lo fa in automatico, e ovviamente ci mette del tempo.
Mentre a C# dovresti farglielo fare tu, cioeā€™ dovresti scrivere tutta questa logica dentro lo script, utilizzando oggetti di tipo object ogni volta che vuoi poter assegnare valori di tipo diverso allo stesso oggetto.

infatti era quello a cui stavo ragionando per aggirare il problema

mi stai confondendo ahahahah

ĆØ semplice, se la selezione non va a buon fine mi ritorna Cancel e finisce tutto
se invece la selezione va a buon fine mi ritorna lā€™oggetto selezionato, in tal caso
prosegue il codice, essendo che questo metodo veniva chiamato da unā€™altro metodo

quindi oggetto restituito viene associato ad unā€™altra variabile per poi essere gestita,
nonā€™ĆØ nessun codice particolare o chissĆ  che, ho solo svolto una gestione a blocchi.
(per lo meno questo credo di aver fatto)

ps cā€™Ć© un doppio controllo ovviamente in entrambi i Metodi

E percheā€™ finisce tutto ?
Se non sai come viene utilizzato il valore restituito, come fai a sapere che finisce tutto ? :slight_smile:

Come prosegue il codice ?
Tu richiami GetCrvs, OK. Resituisce un valore.
Come fai a utilizzare quel valore ?
Non sai nemmeno se eā€™ un GetObject o un Result ā€¦

Da quanto ho forse forse forse capito finora. :wink:
Tu stai cercando un modo per far fare allo script C# una cosa che non sai a cosa serve ā€¦
( Cioeā€™ restituire o un GetObject o un Result )
O almeno, finora non me lo hai detto cosa cā€™eā€™ di tanto utile in un valore che puoā€™ avere due tipi diversi ā€¦
Io non ho visto nessun esempio che richiami quella funzione ā€¦

Capirei se restituisse una tuple con due valori: un GetObject e un Result.
A quel punto tu sai che il primo elemento della tuple eā€™ un GetObject e il secondo un Result.
Quindi puoi controllare il Result:
Se eā€™ OK, usi il GetObjetc per ricavare lā€™oggetto.
Se no termini lo script.

Ma che avere un solo valore di un tipo indefinito sia cosiā€™ utile da dover impazzire per far lavorare C# come se fosse Python ā€¦ a questā€™ora eā€™ proprio oltre le mie misere capacitaā€™ di comprensione ā€¦
:wink: :smile: :smile:

1 Mi Piace
import Rhino as rh

def GetCrv():
    go = rh.Input.Custom.GetObject()
    go.SetCommandPrompt("Sel Crv")
    go.Get()
    if go.CommandResult() != rh.Commands.Result.Success: return go.CommandResult()
    return go.Object(0).Curve()

def Main():
    crv = GetCrv()
    if crv == rh.Commands.Result.Cancel: return print(crv)
    # da qui so che oggetto non'ĆØ un Result.Cancel
    # e con oggetto curva ci faccio quel che voglio.
Main()

mi sa che nella tirata dā€™orecchie mi hai dato la soluzione della tupla giusto. . .
:wink:

edit: ma ora che ricordo, non veniva usata anche una sintassi tipo rc obj oggetto creando una tupla. . .

1 Mi Piace

Se Python controlla solo se il valore eā€™ Cancel, allora percheā€™ non usi null al posto di Cancel ?
Cosiā€™ eā€™ compatibile col tipo restituito. :slightly_smiling_face:

1 Mi Piace
    Rhino.Input.Custom.GetObject go = new Rhino.Input.Custom.GetObject();
    go.SetCommandPrompt( "Select lines" );
    go.GeometryFilter = Rhino.DocObjects.ObjectType.Curve;
    go.GetMultiple( 2, 2);
    if( go.CommandResult() != Rhino.Commands.Result.Success )
      return go.CommandResult();
    if( go.ObjectCount != 2 )
      return Rhino.Commands.Result.Failure;
 
    LineCurve crv0 = go.Object(0).Geometry() as LineCurve;
    LineCurve crv1 = go.Object(1).Geometry() as LineCurve;
    if( crv0==null || crv1==null )

proprio adesso stavo appunto leggendo questo codice di esempio :sob: :sob:

essƬ come soluzione credo sia questa la strada da percorrere, provo nella pratica e ti faccio sapere.

:+1:

1 Mi Piace

comunque il Metodo ĆØ tipizzato come Rhino.Commands.Result
infatti gli oggetti curve vengono lavorate allā€™interno del Metodo stesso

nel caso se possibile, provo con entrambi i metodi poi nel caso scelgo quale preferisco.
(anche se assegnazione di tuple a piĆ¹ variabili mi sembra sia una cosa di Py)

alla prossima :+1:

stamani sono riuscito a usare la tupla:

using sy = System;
using rh = Rhino;

(rh.Commands.Result, rh.Input.Custom.GetObject) GetCrvs()
{
    rh.Input.Custom.GetObject go = new rh.Input.Custom.GetObject();

    go.SetCommandPrompt("Select Object");

    go.Get();
    
    if (go.CommandResult() != rh.Commands.Result.Success) return (go.CommandResult(), go);
    
    sy.Console.WriteLine( go.ObjectCount );

    return (go.CommandResult(), go);
}

(rh.Commands.Result, rh.Input.Custom.GetObject) unknown = GetCrvs();

sy.Console.WriteLine( unknown.Item1 );
sy.Console.WriteLine( unknown.Item2 );

poi ho optato per lā€™altra soluzione auspicata:

rh.Commands.Result Mtd(out object obj_ref)
{
    var go = new rh.Input.Custom.GetObject();

    go.SetCommandPrompt("Sel Crv");
    
    go.Get();
    
    obj_ref = go.Object(0);

    if (go.CommandResult() != rh.Commands.Result.Success) return go.CommandResult();
    
    return go.CommandResult();
}

Main();
void Main()
{
    var rc = Mtd(out object obj);
    
    sy.Console.WriteLine( rc );

    sy.Console.WriteLine(obj);
}

sembra che facciano quello che avevo in mente. . .

quindi nella pratica il Metodo si porta dietro il parametro che ha al suo interno, in questo caso lā€™oggetto.